Merge pull request #381 from GetStream/feature/null-safety
feat: migrate to NNBD(non-nullable by default)
This commit is contained in:
@@ -27,7 +27,7 @@ jobs:
|
||||
./.github/workflows/scripts/install-tools.sh
|
||||
flutter pub global activate tuneup
|
||||
- name: 'Bootstrap Workspace'
|
||||
run: melos bootstrap
|
||||
run: melos bootstrap --verbose
|
||||
- name: 'Dart Analyze'
|
||||
run: |
|
||||
melos exec -c 3 --ignore="*example*" -- \
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
run: |
|
||||
./.github/workflows/scripts/install-tools.sh
|
||||
- name: 'Bootstrap Workspace'
|
||||
run: melos bootstrap
|
||||
run: melos bootstrap --verbose
|
||||
- name: 'Dart'
|
||||
run: |
|
||||
melos exec -c 1 -- \
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
flutter pub global activate coverage
|
||||
flutter pub global activate remove_from_coverage
|
||||
- name: 'Bootstrap Workspace'
|
||||
run: melos bootstrap
|
||||
run: melos bootstrap --verbose
|
||||
- name: 'Dart Test'
|
||||
run: |
|
||||
cd packages/stream_chat
|
||||
|
||||
+1
-2
@@ -59,5 +59,4 @@ dev_dependencies:
|
||||
pedantic: 1.9.2
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
flutter: ">=1.22.4 <2.0.0"
|
||||
sdk: ">=2.12.0 <3.0.0"
|
||||
@@ -1,3 +1,8 @@
|
||||
## 2.0.0-nullsafety.0
|
||||
|
||||
- Migrate this package to null safety
|
||||
- Added typed filters
|
||||
|
||||
## 1.5.3
|
||||
|
||||
- fix: `StreamChatClient.connect` returns quicker when you're using the persistence package
|
||||
|
||||
@@ -3,7 +3,6 @@ analyzer:
|
||||
- lib/**/*.g.dart
|
||||
- lib/**/*.freezed.dart
|
||||
- example/*
|
||||
- test/*
|
||||
linter:
|
||||
rules:
|
||||
- always_use_package_imports
|
||||
|
||||
@@ -4,5 +4,4 @@ targets:
|
||||
json_serializable:
|
||||
options:
|
||||
explicit_to_json: true
|
||||
field_rename: snake
|
||||
any_map: true
|
||||
field_rename: snake
|
||||
Generated
+1
-1
@@ -2,6 +2,6 @@
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
||||
@@ -2,12 +2,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
/// Create a new instance of [StreamChatClient] passing the apikey obtained from your
|
||||
/// project dashboard.
|
||||
final client = StreamChatClient(
|
||||
'b67pax5b2wdq',
|
||||
logLevel: Level.INFO,
|
||||
);
|
||||
/// Create a new instance of [StreamChatClient]
|
||||
/// by passing the apikey obtained from your project dashboard.
|
||||
final client = StreamChatClient('b67pax5b2wdq', logLevel: Level.INFO);
|
||||
|
||||
/// Set the current user. In a production scenario, this should be done using
|
||||
/// a backend to generate a user token using our server SDK.
|
||||
@@ -21,7 +18,7 @@ Future<void> main() async {
|
||||
'https://getstream.io/random_png/?id=cool-shadow-7&name=Cool+shadow',
|
||||
},
|
||||
),
|
||||
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY29vbC1zaGFkb3ctNyJ9.gkOlCRb1qgy4joHPaxFwPOdXcGvSPvp6QY0S4mpRkVo',
|
||||
'''eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY29vbC1zaGFkb3ctNyJ9.gkOlCRb1qgy4joHPaxFwPOdXcGvSPvp6QY0S4mpRkVo''',
|
||||
);
|
||||
|
||||
/// Creates a channel using the type `messaging` and `godevs`.
|
||||
@@ -44,15 +41,16 @@ Future<void> main() async {
|
||||
|
||||
/// Example using Stream's Low Level Dart client.
|
||||
class StreamExample extends StatelessWidget {
|
||||
/// To initialize this example, an instance of [client] and [channel] is required.
|
||||
/// To initialize this example, an instance of
|
||||
/// [client] and [channel] is required.
|
||||
const StreamExample({
|
||||
Key key,
|
||||
@required this.client,
|
||||
@required this.channel,
|
||||
Key? key,
|
||||
required this.client,
|
||||
required this.channel,
|
||||
}) : super(key: key);
|
||||
|
||||
/// Instance of [StreamChatClient] we created earlier. This contains information about
|
||||
/// our application and connection state.
|
||||
/// Instance of [StreamChatClient] we created earlier.
|
||||
/// This contains information about our application and connection state.
|
||||
final StreamChatClient client;
|
||||
|
||||
/// The channel we'd like to observe and participate.
|
||||
@@ -71,28 +69,31 @@ class StreamExample extends StatelessWidget {
|
||||
/// containing the channel name and a [MessageView] displaying recent messages.
|
||||
class HomeScreen extends StatelessWidget {
|
||||
/// [HomeScreen] is constructed using the [Channel] we defined earlier.
|
||||
const HomeScreen({Key key, @required this.channel}) : super(key: key);
|
||||
const HomeScreen({
|
||||
Key? key,
|
||||
required this.channel,
|
||||
}) : super(key: key);
|
||||
|
||||
/// Channel object containing the [Channel.id] we'd like to observe.
|
||||
final Channel channel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final messages = channel.state.channelStateStream;
|
||||
final messages = channel.state!.channelStateStream;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Channel: ${channel.id}'),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: StreamBuilder<ChannelState>(
|
||||
child: StreamBuilder<ChannelState?>(
|
||||
stream: messages,
|
||||
builder: (
|
||||
BuildContext context,
|
||||
AsyncSnapshot<ChannelState> snapshot,
|
||||
AsyncSnapshot<ChannelState?> snapshot,
|
||||
) {
|
||||
if (snapshot.hasData && snapshot.data != null) {
|
||||
return MessageView(
|
||||
messages: snapshot.data.messages.reversed.toList(),
|
||||
messages: snapshot.data!.messages.reversed.toList(),
|
||||
channel: channel,
|
||||
);
|
||||
} else if (snapshot.hasError) {
|
||||
@@ -104,8 +105,8 @@ class HomeScreen extends StatelessWidget {
|
||||
}
|
||||
return const Center(
|
||||
child: SizedBox(
|
||||
width: 100.0,
|
||||
height: 100.0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
@@ -121,9 +122,9 @@ class HomeScreen extends StatelessWidget {
|
||||
class MessageView extends StatefulWidget {
|
||||
/// Message takes the latest list of messages and the current channel.
|
||||
const MessageView({
|
||||
Key key,
|
||||
@required this.messages,
|
||||
@required this.channel,
|
||||
Key? key,
|
||||
required this.messages,
|
||||
required this.channel,
|
||||
}) : super(key: key);
|
||||
|
||||
/// List of messages sent in the given channel.
|
||||
@@ -137,8 +138,8 @@ class MessageView extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MessageViewState extends State<MessageView> {
|
||||
TextEditingController _controller;
|
||||
ScrollController _scrollController;
|
||||
late final TextEditingController _controller;
|
||||
late final ScrollController _scrollController;
|
||||
|
||||
List<Message> get _messages => widget.messages;
|
||||
|
||||
@@ -176,20 +177,20 @@ class _MessageViewState extends State<MessageView> {
|
||||
reverse: true,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final item = _messages[index];
|
||||
if (item.user.id == widget.channel.client.uid) {
|
||||
if (item.user?.id == widget.channel.client.uid) {
|
||||
return Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(item.text),
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Text(item.text ?? ''),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(item.text),
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Text(item.text ?? ''),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -197,7 +198,7 @@ class _MessageViewState extends State<MessageView> {
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
@@ -245,7 +246,8 @@ class _MessageViewState extends State<MessageView> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper extension for quickly retrieving the current user id from a [StreamChatClient].
|
||||
/// Helper extension for quickly retrieving
|
||||
/// the current user id from a [StreamChatClient].
|
||||
extension on StreamChatClient {
|
||||
String get uid => state.user.id;
|
||||
String get uid => state.user!.id;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
name: example
|
||||
description: A new Flutter project.
|
||||
|
||||
publish_to: 'none'
|
||||
publish_to: "none"
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
cupertino_icons: ^1.0.0
|
||||
flutter:
|
||||
sdk: flutter
|
||||
cupertino_icons: ^1.0.0
|
||||
stream_chat:
|
||||
stream_chat:
|
||||
path: ../
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
uses-material-design: true
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,7 @@ class SortOption<T> {
|
||||
|
||||
/// Sorting field Comparator required for offline sorting
|
||||
@JsonKey(ignore: true)
|
||||
final Comparator<T> comparator;
|
||||
final Comparator<T>? comparator;
|
||||
|
||||
/// Serialize model to json
|
||||
Map<String, dynamic> toJson() => _$SortOptionToJson(this);
|
||||
@@ -70,31 +70,31 @@ class PaginationParams {
|
||||
|
||||
/// Filter on ids greater than the given value.
|
||||
@JsonKey(name: 'id_gt')
|
||||
final String greaterThan;
|
||||
final String? greaterThan;
|
||||
|
||||
/// Filter on ids greater than or equal to the given value.
|
||||
@JsonKey(name: 'id_gte')
|
||||
final String greaterThanOrEqual;
|
||||
final String? greaterThanOrEqual;
|
||||
|
||||
/// Filter on ids smaller than the given value.
|
||||
@JsonKey(name: 'id_lt')
|
||||
final String lessThan;
|
||||
final String? lessThan;
|
||||
|
||||
/// Filter on ids smaller than or equal to the given value.
|
||||
@JsonKey(name: 'id_lte')
|
||||
final String lessThanOrEqual;
|
||||
final String? lessThanOrEqual;
|
||||
|
||||
/// Serialize model to json
|
||||
Map<String, dynamic> toJson() => _$PaginationParamsToJson(this);
|
||||
|
||||
/// Creates a copy of [PaginationParams] with specified attributes overridden.
|
||||
PaginationParams copyWith({
|
||||
int limit,
|
||||
int offset,
|
||||
String greaterThan,
|
||||
String greaterThanOrEqual,
|
||||
String lessThan,
|
||||
String lessThanOrEqual,
|
||||
int? limit,
|
||||
int? offset,
|
||||
String? greaterThan,
|
||||
String? greaterThanOrEqual,
|
||||
String? lessThan,
|
||||
String? lessThanOrEqual,
|
||||
}) =>
|
||||
PaginationParams(
|
||||
limit: limit ?? this.limit,
|
||||
@@ -106,6 +106,7 @@ class PaginationParams {
|
||||
);
|
||||
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
int get hashCode =>
|
||||
runtimeType.hashCode ^
|
||||
limit.hashCode ^
|
||||
|
||||
@@ -13,7 +13,10 @@ Map<String, dynamic> _$SortOptionToJson<T>(SortOption<T> instance) =>
|
||||
};
|
||||
|
||||
Map<String, dynamic> _$PaginationParamsToJson(PaginationParams instance) {
|
||||
final val = <String, dynamic>{};
|
||||
final val = <String, dynamic>{
|
||||
'limit': instance.limit,
|
||||
'offset': instance.offset,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
@@ -21,8 +24,6 @@ Map<String, dynamic> _$PaginationParamsToJson(PaginationParams instance) {
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('limit', instance.limit);
|
||||
writeNotNull('offset', instance.offset);
|
||||
writeNotNull('id_gt', instance.greaterThan);
|
||||
writeNotNull('id_gte', instance.greaterThanOrEqual);
|
||||
writeNotNull('id_lt', instance.lessThan);
|
||||
|
||||
@@ -13,14 +13,15 @@ import 'package:stream_chat/src/models/user.dart';
|
||||
part 'responses.g.dart';
|
||||
|
||||
class _BaseResponse {
|
||||
String duration;
|
||||
String? duration;
|
||||
}
|
||||
|
||||
/// Model response for [StreamChatClient.resync] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SyncResponse extends _BaseResponse {
|
||||
/// The list of events
|
||||
List<Event> events;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Event> events;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SyncResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -31,7 +32,8 @@ class SyncResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryChannelsResponse extends _BaseResponse {
|
||||
/// List of channels state returned by the query
|
||||
List<ChannelState> channels;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<ChannelState> channels;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryChannelsResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -41,8 +43,8 @@ class QueryChannelsResponse extends _BaseResponse {
|
||||
/// Model response for [StreamChatClient.queryChannels] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class TranslateMessageResponse extends _BaseResponse {
|
||||
/// List of channels state returned by the query
|
||||
TranslatedMessage message;
|
||||
/// Translated message
|
||||
late TranslatedMessage message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static TranslateMessageResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -53,7 +55,8 @@ class TranslateMessageResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryMembersResponse extends _BaseResponse {
|
||||
/// List of channels state returned by the query
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryMembersResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -64,7 +67,8 @@ class QueryMembersResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryUsersResponse extends _BaseResponse {
|
||||
/// List of users returned by the query
|
||||
List<User> users;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<User> users;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryUsersResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -75,7 +79,8 @@ class QueryUsersResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryReactionsResponse extends _BaseResponse {
|
||||
/// List of reactions returned by the query
|
||||
List<Reaction> reactions;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Reaction> reactions;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryReactionsResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -86,7 +91,8 @@ class QueryReactionsResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryRepliesResponse extends _BaseResponse {
|
||||
/// List of messages returned by the api call
|
||||
List<Message> messages;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Message> messages;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryRepliesResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -97,7 +103,8 @@ class QueryRepliesResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class ListDevicesResponse extends _BaseResponse {
|
||||
/// List of user devices
|
||||
List<Device> devices;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Device> devices;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static ListDevicesResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -108,7 +115,7 @@ class ListDevicesResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendFileResponse extends _BaseResponse {
|
||||
/// The url of the uploaded file
|
||||
String file;
|
||||
late String file;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendFileResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -119,7 +126,7 @@ class SendFileResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendImageResponse extends _BaseResponse {
|
||||
/// The url of the uploaded file
|
||||
String file;
|
||||
late String file;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendImageResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -130,10 +137,10 @@ class SendImageResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendReactionResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
late Message message;
|
||||
|
||||
/// The reaction created by the api call
|
||||
Reaction reaction;
|
||||
late Reaction reaction;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendReactionResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -144,10 +151,10 @@ class SendReactionResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class ConnectGuestUserResponse extends _BaseResponse {
|
||||
/// Guest user access token
|
||||
String accessToken;
|
||||
late String accessToken;
|
||||
|
||||
/// Guest user
|
||||
User user;
|
||||
late User user;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static ConnectGuestUserResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -158,7 +165,8 @@ class ConnectGuestUserResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class UpdateUsersResponse extends _BaseResponse {
|
||||
/// Updated users
|
||||
Map<String, User> users;
|
||||
@JsonKey(defaultValue: {})
|
||||
late Map<String, User> users;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static UpdateUsersResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -169,7 +177,7 @@ class UpdateUsersResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class UpdateMessageResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
late Message message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static UpdateMessageResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -180,7 +188,7 @@ class UpdateMessageResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendMessageResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
late Message message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendMessageResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -191,17 +199,17 @@ class SendMessageResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class GetMessageResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
late Message message;
|
||||
|
||||
/// Channel of the message
|
||||
ChannelModel channel;
|
||||
ChannelModel? channel;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static GetMessageResponse fromJson(Map<String, dynamic> json) {
|
||||
final res = _$GetMessageResponseFromJson(json);
|
||||
final jsonChannel = res.message?.extraData?.remove('channel');
|
||||
final jsonChannel = res.message.extraData.remove('channel');
|
||||
if (jsonChannel != null) {
|
||||
res.channel = ChannelModel.fromJson(jsonChannel);
|
||||
res.channel = ChannelModel.fromJson(jsonChannel as Map<String, dynamic>);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -211,7 +219,8 @@ class GetMessageResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SearchMessagesResponse extends _BaseResponse {
|
||||
/// List of messages returned by the api call
|
||||
List<GetMessageResponse> results;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<GetMessageResponse> results;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SearchMessagesResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -222,7 +231,8 @@ class SearchMessagesResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class GetMessagesByIdResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
List<Message> messages;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Message> messages;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static GetMessagesByIdResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -233,13 +243,13 @@ class GetMessagesByIdResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class UpdateChannelResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
List<Member>? members;
|
||||
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static UpdateChannelResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -250,10 +260,10 @@ class UpdateChannelResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class PartialUpdateChannelResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
List<Member>? members;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static PartialUpdateChannelResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -264,13 +274,14 @@ class PartialUpdateChannelResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class InviteMembersResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static InviteMembersResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -281,13 +292,14 @@ class InviteMembersResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class RemoveMembersResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static RemoveMembersResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -298,7 +310,7 @@ class RemoveMembersResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendActionResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendActionResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -309,13 +321,14 @@ class SendActionResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class AddMembersResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static AddMembersResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -326,13 +339,14 @@ class AddMembersResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class AcceptInviteResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static AcceptInviteResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -343,13 +357,14 @@ class AcceptInviteResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class RejectInviteResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static RejectInviteResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -368,19 +383,23 @@ class EmptyResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class ChannelStateResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// List of messages returned by the api call
|
||||
List<Message> messages;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Message> messages;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Number of users watching the channel
|
||||
int watcherCount;
|
||||
@JsonKey(defaultValue: 0)
|
||||
late int watcherCount;
|
||||
|
||||
/// List of read states
|
||||
List<Read> read;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Read> read;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static ChannelStateResponse fromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -6,394 +6,274 @@ part of 'responses.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
SyncResponse _$SyncResponseFromJson(Map json) {
|
||||
SyncResponse _$SyncResponseFromJson(Map<String, dynamic> json) {
|
||||
return SyncResponse()
|
||||
..duration = json['duration'] as String
|
||||
..events = (json['events'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Event.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..events = (json['events'] as List<dynamic>?)
|
||||
?.map((e) => Event.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
QueryChannelsResponse _$QueryChannelsResponseFromJson(Map json) {
|
||||
QueryChannelsResponse _$QueryChannelsResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return QueryChannelsResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channels = (json['channels'] as List)
|
||||
?.map((e) => e == null ? null : ChannelState.fromJson(e as Map))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..channels = (json['channels'] as List<dynamic>?)
|
||||
?.map((e) => ChannelState.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
TranslateMessageResponse _$TranslateMessageResponseFromJson(Map json) {
|
||||
TranslateMessageResponse _$TranslateMessageResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return TranslateMessageResponse()
|
||||
..duration = json['duration'] as String
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: TranslatedMessage.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
..duration = json['duration'] as String?
|
||||
..message =
|
||||
TranslatedMessage.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
QueryMembersResponse _$QueryMembersResponseFromJson(Map json) {
|
||||
QueryMembersResponse _$QueryMembersResponseFromJson(Map<String, dynamic> json) {
|
||||
return QueryMembersResponse()
|
||||
..duration = json['duration'] as String
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
QueryUsersResponse _$QueryUsersResponseFromJson(Map json) {
|
||||
QueryUsersResponse _$QueryUsersResponseFromJson(Map<String, dynamic> json) {
|
||||
return QueryUsersResponse()
|
||||
..duration = json['duration'] as String
|
||||
..users = (json['users'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: User.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..users = (json['users'] as List<dynamic>?)
|
||||
?.map((e) => User.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
QueryReactionsResponse _$QueryReactionsResponseFromJson(Map json) {
|
||||
QueryReactionsResponse _$QueryReactionsResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return QueryReactionsResponse()
|
||||
..duration = json['duration'] as String
|
||||
..reactions = (json['reactions'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Reaction.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..reactions = (json['reactions'] as List<dynamic>?)
|
||||
?.map((e) => Reaction.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
QueryRepliesResponse _$QueryRepliesResponseFromJson(Map json) {
|
||||
QueryRepliesResponse _$QueryRepliesResponseFromJson(Map<String, dynamic> json) {
|
||||
return QueryRepliesResponse()
|
||||
..duration = json['duration'] as String
|
||||
..messages = (json['messages'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Message.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..messages = (json['messages'] as List<dynamic>?)
|
||||
?.map((e) => Message.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
ListDevicesResponse _$ListDevicesResponseFromJson(Map json) {
|
||||
ListDevicesResponse _$ListDevicesResponseFromJson(Map<String, dynamic> json) {
|
||||
return ListDevicesResponse()
|
||||
..duration = json['duration'] as String
|
||||
..devices = (json['devices'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Device.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..devices = (json['devices'] as List<dynamic>?)
|
||||
?.map((e) => Device.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
SendFileResponse _$SendFileResponseFromJson(Map json) {
|
||||
SendFileResponse _$SendFileResponseFromJson(Map<String, dynamic> json) {
|
||||
return SendFileResponse()
|
||||
..duration = json['duration'] as String
|
||||
..duration = json['duration'] as String?
|
||||
..file = json['file'] as String;
|
||||
}
|
||||
|
||||
SendImageResponse _$SendImageResponseFromJson(Map json) {
|
||||
SendImageResponse _$SendImageResponseFromJson(Map<String, dynamic> json) {
|
||||
return SendImageResponse()
|
||||
..duration = json['duration'] as String
|
||||
..duration = json['duration'] as String?
|
||||
..file = json['file'] as String;
|
||||
}
|
||||
|
||||
SendReactionResponse _$SendReactionResponseFromJson(Map json) {
|
||||
SendReactionResponse _$SendReactionResponseFromJson(Map<String, dynamic> json) {
|
||||
return SendReactionResponse()
|
||||
..duration = json['duration'] as String
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..reaction = json['reaction'] == null
|
||||
? null
|
||||
: Reaction.fromJson((json['reaction'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
..duration = json['duration'] as String?
|
||||
..message = Message.fromJson(json['message'] as Map<String, dynamic>)
|
||||
..reaction = Reaction.fromJson(json['reaction'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
ConnectGuestUserResponse _$ConnectGuestUserResponseFromJson(Map json) {
|
||||
ConnectGuestUserResponse _$ConnectGuestUserResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return ConnectGuestUserResponse()
|
||||
..duration = json['duration'] as String
|
||||
..duration = json['duration'] as String?
|
||||
..accessToken = json['access_token'] as String
|
||||
..user = json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
..user = User.fromJson(json['user'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
UpdateUsersResponse _$UpdateUsersResponseFromJson(Map json) {
|
||||
UpdateUsersResponse _$UpdateUsersResponseFromJson(Map<String, dynamic> json) {
|
||||
return UpdateUsersResponse()
|
||||
..duration = json['duration'] as String
|
||||
..users = (json['users'] as Map)?.map(
|
||||
(k, e) => MapEntry(
|
||||
k as String,
|
||||
e == null
|
||||
? null
|
||||
: User.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))),
|
||||
);
|
||||
..duration = json['duration'] as String?
|
||||
..users = (json['users'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, User.fromJson(e as Map<String, dynamic>)),
|
||||
) ??
|
||||
{};
|
||||
}
|
||||
|
||||
UpdateMessageResponse _$UpdateMessageResponseFromJson(Map json) {
|
||||
UpdateMessageResponse _$UpdateMessageResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return UpdateMessageResponse()
|
||||
..duration = json['duration'] as String
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
..duration = json['duration'] as String?
|
||||
..message = Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
SendMessageResponse _$SendMessageResponseFromJson(Map json) {
|
||||
SendMessageResponse _$SendMessageResponseFromJson(Map<String, dynamic> json) {
|
||||
return SendMessageResponse()
|
||||
..duration = json['duration'] as String
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
..duration = json['duration'] as String?
|
||||
..message = Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
GetMessageResponse _$GetMessageResponseFromJson(Map json) {
|
||||
GetMessageResponse _$GetMessageResponseFromJson(Map<String, dynamic> json) {
|
||||
return GetMessageResponse()
|
||||
..duration = json['duration'] as String
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..duration = json['duration'] as String?
|
||||
..message = Message.fromJson(json['message'] as Map<String, dynamic>)
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: ChannelModel.fromJson(json['channel'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
SearchMessagesResponse _$SearchMessagesResponseFromJson(Map json) {
|
||||
SearchMessagesResponse _$SearchMessagesResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return SearchMessagesResponse()
|
||||
..duration = json['duration'] as String
|
||||
..results = (json['results'] as List)
|
||||
?.map((e) => e == null ? null : GetMessageResponse.fromJson(e as Map))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..results = (json['results'] as List<dynamic>?)
|
||||
?.map((e) => GetMessageResponse.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
GetMessagesByIdResponse _$GetMessagesByIdResponseFromJson(Map json) {
|
||||
GetMessagesByIdResponse _$GetMessagesByIdResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return GetMessagesByIdResponse()
|
||||
..duration = json['duration'] as String
|
||||
..messages = (json['messages'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Message.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..messages = (json['messages'] as List<dynamic>?)
|
||||
?.map((e) => Message.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
UpdateChannelResponse _$UpdateChannelResponseFromJson(Map json) {
|
||||
UpdateChannelResponse _$UpdateChannelResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return UpdateChannelResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList()
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
PartialUpdateChannelResponse _$PartialUpdateChannelResponseFromJson(Map json) {
|
||||
PartialUpdateChannelResponse _$PartialUpdateChannelResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return PartialUpdateChannelResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
}
|
||||
|
||||
InviteMembersResponse _$InviteMembersResponseFromJson(Map json) {
|
||||
InviteMembersResponse _$InviteMembersResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return InviteMembersResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
RemoveMembersResponse _$RemoveMembersResponseFromJson(Map json) {
|
||||
RemoveMembersResponse _$RemoveMembersResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return RemoveMembersResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
SendActionResponse _$SendActionResponseFromJson(Map json) {
|
||||
SendActionResponse _$SendActionResponseFromJson(Map<String, dynamic> json) {
|
||||
return SendActionResponse()
|
||||
..duration = json['duration'] as String
|
||||
..duration = json['duration'] as String?
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
AddMembersResponse _$AddMembersResponseFromJson(Map json) {
|
||||
AddMembersResponse _$AddMembersResponseFromJson(Map<String, dynamic> json) {
|
||||
return AddMembersResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
AcceptInviteResponse _$AcceptInviteResponseFromJson(Map json) {
|
||||
AcceptInviteResponse _$AcceptInviteResponseFromJson(Map<String, dynamic> json) {
|
||||
return AcceptInviteResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
RejectInviteResponse _$RejectInviteResponseFromJson(Map json) {
|
||||
RejectInviteResponse _$RejectInviteResponseFromJson(Map<String, dynamic> json) {
|
||||
return RejectInviteResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
EmptyResponse _$EmptyResponseFromJson(Map json) {
|
||||
return EmptyResponse()..duration = json['duration'] as String;
|
||||
EmptyResponse _$EmptyResponseFromJson(Map<String, dynamic> json) {
|
||||
return EmptyResponse()..duration = json['duration'] as String?;
|
||||
}
|
||||
|
||||
ChannelStateResponse _$ChannelStateResponseFromJson(Map json) {
|
||||
ChannelStateResponse _$ChannelStateResponseFromJson(Map<String, dynamic> json) {
|
||||
return ChannelStateResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..messages = (json['messages'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Message.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..watcherCount = json['watcher_count'] as int
|
||||
..read = (json['read'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Read.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..messages = (json['messages'] as List<dynamic>?)
|
||||
?.map((e) => Message.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..watcherCount = json['watcher_count'] as int? ?? 0
|
||||
..read = (json['read'] as List<dynamic>?)
|
||||
?.map((e) => Read.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:stream_chat/src/client.dart';
|
||||
import 'package:stream_chat/src/exceptions.dart';
|
||||
|
||||
@@ -6,30 +5,30 @@ import 'package:stream_chat/src/exceptions.dart';
|
||||
class RetryPolicy {
|
||||
/// Instantiate a new RetryPolicy
|
||||
RetryPolicy({
|
||||
@required this.shouldRetry,
|
||||
@required this.retryTimeout,
|
||||
this.attempt,
|
||||
required this.shouldRetry,
|
||||
required this.retryTimeout,
|
||||
this.attempt = 0,
|
||||
});
|
||||
|
||||
/// The number of attempts tried so far
|
||||
int attempt = 0;
|
||||
|
||||
/// This function evaluates if we should retry the failure
|
||||
final bool Function(StreamChatClient client, int attempt, ApiError apiError)
|
||||
final bool Function(StreamChatClient client, int attempt, ApiError? apiError)
|
||||
shouldRetry;
|
||||
|
||||
/// In the case that we want to retry a failed request the retryTimeout
|
||||
/// method is called to determine the timeout
|
||||
final Duration Function(
|
||||
StreamChatClient client, int attempt, ApiError apiError) retryTimeout;
|
||||
StreamChatClient client, int attempt, ApiError? apiError) retryTimeout;
|
||||
|
||||
/// Creates a copy of [RetryPolicy] with specified attributes overridden.
|
||||
RetryPolicy copyWith({
|
||||
bool Function(StreamChatClient client, int attempt, ApiError apiError)
|
||||
bool Function(StreamChatClient client, int attempt, ApiError? apiError)?
|
||||
shouldRetry,
|
||||
Duration Function(StreamChatClient client, int attempt, ApiError apiError)
|
||||
Duration Function(StreamChatClient client, int attempt, ApiError? apiError)?
|
||||
retryTimeout,
|
||||
int attempt,
|
||||
int? attempt,
|
||||
}) =>
|
||||
RetryPolicy(
|
||||
retryTimeout: retryTimeout ?? this.retryTimeout,
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'dart:async';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:stream_chat/src/api/channel.dart';
|
||||
import 'package:stream_chat/src/api/retry_policy.dart';
|
||||
import 'package:stream_chat/src/event_type.dart';
|
||||
@@ -14,7 +13,7 @@ import 'package:stream_chat/stream_chat.dart';
|
||||
class RetryQueue {
|
||||
/// Instantiate a new RetryQueue object
|
||||
RetryQueue({
|
||||
@required this.channel,
|
||||
required this.channel,
|
||||
this.logger,
|
||||
}) {
|
||||
_retryPolicy = channel.client.retryPolicy;
|
||||
@@ -28,14 +27,14 @@ class RetryQueue {
|
||||
final Channel channel;
|
||||
|
||||
/// The logger associated to this queue
|
||||
final Logger logger;
|
||||
final Logger? logger;
|
||||
|
||||
final _subscriptions = <StreamSubscription>[];
|
||||
|
||||
void _listenConnectionRecovered() {
|
||||
_subscriptions
|
||||
.add(channel.client.on(EventType.connectionRecovered).listen((event) {
|
||||
if (!_isRetrying && event.online) {
|
||||
if (!_isRetrying && event.online!) {
|
||||
_startRetrying();
|
||||
}
|
||||
}));
|
||||
@@ -43,12 +42,13 @@ class RetryQueue {
|
||||
|
||||
final HeapPriorityQueue<Message> _messageQueue = HeapPriorityQueue(_byDate);
|
||||
bool _isRetrying = false;
|
||||
RetryPolicy _retryPolicy;
|
||||
RetryPolicy? _retryPolicy;
|
||||
|
||||
/// Add a list of messages
|
||||
void add(List<Message> messages) {
|
||||
logger?.info('added ${messages.length} messages');
|
||||
final messageList = _messageQueue.toList();
|
||||
|
||||
_messageQueue.addAll(messages
|
||||
.where((element) => !messageList.any((m) => m.id == element.id)));
|
||||
|
||||
@@ -60,7 +60,7 @@ class RetryQueue {
|
||||
Future<void> _startRetrying() async {
|
||||
logger?.info('start retrying');
|
||||
_isRetrying = true;
|
||||
final retryPolicy = _retryPolicy.copyWith(attempt: 0);
|
||||
final retryPolicy = _retryPolicy!.copyWith(attempt: 0);
|
||||
|
||||
while (_messageQueue.isNotEmpty) {
|
||||
final message = _messageQueue.first;
|
||||
@@ -72,9 +72,9 @@ 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) {
|
||||
if (error.type == DioErrorType.response) {
|
||||
_messageQueue.remove(message);
|
||||
return;
|
||||
}
|
||||
@@ -84,7 +84,7 @@ class RetryQueue {
|
||||
);
|
||||
} else if (error is ApiError) {
|
||||
apiError = error;
|
||||
if (apiError.status?.toString()?.startsWith('4') == true) {
|
||||
if (apiError.status?.toString().startsWith('4') == true) {
|
||||
_messageQueue.remove(message);
|
||||
return;
|
||||
}
|
||||
@@ -101,6 +101,7 @@ class RetryQueue {
|
||||
}
|
||||
|
||||
retryPolicy.attempt++;
|
||||
|
||||
final timeout = retryPolicy.retryTimeout(
|
||||
channel.client,
|
||||
retryPolicy.attempt,
|
||||
@@ -112,13 +113,13 @@ class RetryQueue {
|
||||
_isRetrying = false;
|
||||
}
|
||||
|
||||
void _sendFailedEvent(Message message) {
|
||||
final newStatus = message.status == MessageSendingStatus.sending
|
||||
void _sendFailedEvent(Message? message) {
|
||||
final newStatus = message!.status == MessageSendingStatus.sending
|
||||
? MessageSendingStatus.failed
|
||||
: (message.status == MessageSendingStatus.updating
|
||||
? MessageSendingStatus.failed_update
|
||||
: MessageSendingStatus.failed_delete);
|
||||
channel.state.addMessage(message.copyWith(
|
||||
channel.state!.addMessage(message.copyWith(
|
||||
status: newStatus,
|
||||
));
|
||||
}
|
||||
@@ -141,20 +142,24 @@ class RetryQueue {
|
||||
final messageList = _messageQueue.toList();
|
||||
if (event.message != null) {
|
||||
final messageIndex =
|
||||
messageList.indexWhere((m) => m.id == event.message.id);
|
||||
messageList.indexWhere((m) => m.id == event.message!.id);
|
||||
if (messageIndex == -1 &&
|
||||
[
|
||||
MessageSendingStatus.failed_update,
|
||||
MessageSendingStatus.failed,
|
||||
MessageSendingStatus.failed_delete,
|
||||
].contains(event.message.status)) {
|
||||
].contains(event.message!.status)) {
|
||||
logger?.info('add message from events');
|
||||
add([event.message]);
|
||||
final m = event.message;
|
||||
|
||||
if (m != null) {
|
||||
add([m]);
|
||||
}
|
||||
} else if (messageIndex != -1 &&
|
||||
[
|
||||
MessageSendingStatus.sent,
|
||||
null,
|
||||
].contains(event.message.status)) {
|
||||
].contains(event.message!.status)) {
|
||||
_messageQueue.remove(messageList[messageIndex]);
|
||||
}
|
||||
}
|
||||
@@ -171,10 +176,14 @@ class RetryQueue {
|
||||
final date1 = _getMessageDate(m1);
|
||||
final date2 = _getMessageDate(m2);
|
||||
|
||||
if (date1 == null || date2 == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return date1.compareTo(date2);
|
||||
}
|
||||
|
||||
static DateTime _getMessageDate(Message m1) {
|
||||
static DateTime? _getMessageDate(Message m1) {
|
||||
switch (m1.status) {
|
||||
case MessageSendingStatus.failed_delete:
|
||||
case MessageSendingStatus.deleting:
|
||||
|
||||
@@ -3,5 +3,5 @@ import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
|
||||
/// Html version of websocket implementation
|
||||
/// Used in Flutter web version
|
||||
WebSocketChannel connectWebSocket(String url, {Iterable<String> protocols}) =>
|
||||
WebSocketChannel connectWebSocket(String url, {Iterable<String>? protocols}) =>
|
||||
HtmlWebSocketChannel.connect(url, protocols: protocols);
|
||||
|
||||
@@ -3,5 +3,5 @@ import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
|
||||
/// IO version of websocket implementation
|
||||
/// Used in Flutter mobile version
|
||||
WebSocketChannel connectWebSocket(String url, {Iterable<String> protocols}) =>
|
||||
WebSocketChannel connectWebSocket(String url, {Iterable<String>? protocols}) =>
|
||||
IOWebSocketChannel.connect(url, protocols: protocols);
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
/// Stub version of websocket implementation
|
||||
/// Used just for conditional library import
|
||||
WebSocketChannel connectWebSocket(String url,
|
||||
{Iterable<String> protocols,
|
||||
Map<String, dynamic> headers,
|
||||
Duration pingInterval}) =>
|
||||
{Iterable<String>? protocols,
|
||||
Map<String, dynamic>? headers,
|
||||
Duration? pingInterval}) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
@@ -16,8 +16,8 @@ typedef EventHandler = void Function(Event);
|
||||
/// Typedef used for connecting to a websocket. Method returns a
|
||||
/// [WebSocketChannel] and accepts a connection [url] and an optional
|
||||
/// [Iterable] of `protocols`.
|
||||
typedef ConnectWebSocket = WebSocketChannel Function(String url,
|
||||
{Iterable<String> protocols});
|
||||
typedef ConnectWebSocket = WebSocketChannel Function(String? url,
|
||||
{Iterable<String>? protocols});
|
||||
|
||||
// TODO: parse error even
|
||||
// TODO: if parsing an error into an event fails we should not hide the
|
||||
@@ -27,11 +27,11 @@ class WebSocket {
|
||||
/// Creates a new websocket
|
||||
/// To connect the WS call [connect]
|
||||
WebSocket({
|
||||
@required this.baseUrl,
|
||||
this.user,
|
||||
this.connectParams,
|
||||
this.connectPayload,
|
||||
this.handler,
|
||||
required this.baseUrl,
|
||||
required this.user,
|
||||
required this.handler,
|
||||
this.connectParams = const {},
|
||||
this.connectPayload = const {},
|
||||
this.logger,
|
||||
this.connectFunc,
|
||||
this.reconnectionMonitorInterval = 1,
|
||||
@@ -78,12 +78,12 @@ class WebSocket {
|
||||
final EventHandler handler;
|
||||
|
||||
/// A WS specific logger instance
|
||||
final Logger logger;
|
||||
final Logger? logger;
|
||||
|
||||
/// Connection function
|
||||
/// Used only for testing purpose
|
||||
@visibleForTesting
|
||||
final ConnectWebSocket connectFunc;
|
||||
final ConnectWebSocket? connectFunc;
|
||||
|
||||
/// Interval of the reconnection monitor timer
|
||||
/// This checks that it received a new event in the last
|
||||
@@ -107,43 +107,43 @@ class WebSocket {
|
||||
_connectionStatusController.add(status);
|
||||
|
||||
/// The current connection status value
|
||||
ConnectionStatus get connectionStatus => _connectionStatusController.value;
|
||||
ConnectionStatus? get connectionStatus => _connectionStatusController.value;
|
||||
|
||||
/// This notifies of connection status changes
|
||||
Stream<ConnectionStatus> get connectionStatusStream =>
|
||||
_connectionStatusController.stream;
|
||||
|
||||
String _path;
|
||||
late String _path;
|
||||
int _retryAttempt = 1;
|
||||
WebSocketChannel _channel;
|
||||
Timer _healthCheck, _reconnectionMonitor;
|
||||
DateTime _lastEventAt;
|
||||
late WebSocketChannel _channel;
|
||||
Timer? _healthCheck, _reconnectionMonitor;
|
||||
DateTime? _lastEventAt;
|
||||
bool _manuallyDisconnected = false;
|
||||
bool _connecting = false;
|
||||
bool _reconnecting = false;
|
||||
|
||||
Event _decodeEvent(String source) => Event.fromJson(json.decode(source));
|
||||
|
||||
Completer<Event> _connectionCompleter = Completer<Event>();
|
||||
Completer<Event?> _connectionCompleter = Completer<Event?>();
|
||||
|
||||
/// Connect the WS using the parameters passed in the constructor
|
||||
Future<Event> connect() {
|
||||
Future<Event?> connect() async {
|
||||
_manuallyDisconnected = false;
|
||||
|
||||
if (_connecting) {
|
||||
logger.severe('already connecting');
|
||||
logger?.severe('already connecting');
|
||||
return null;
|
||||
}
|
||||
|
||||
_connecting = true;
|
||||
_connectionStatus = ConnectionStatus.connecting;
|
||||
|
||||
logger.info('connecting to $_path');
|
||||
logger?.info('connecting to $_path');
|
||||
|
||||
_channel =
|
||||
connectFunc?.call(_path) ?? WebSocketChannel.connect(Uri.parse(_path));
|
||||
_channel.stream.listen(
|
||||
(data) {
|
||||
(data) async {
|
||||
final jsonData = json.decode(data);
|
||||
if (jsonData['error'] != null) {
|
||||
return _onConnectionError(jsonData['error']);
|
||||
@@ -153,9 +153,7 @@ class WebSocket {
|
||||
onError: (error, stacktrace) {
|
||||
_onConnectionError(error, stacktrace);
|
||||
},
|
||||
onDone: () {
|
||||
_onDone();
|
||||
},
|
||||
onDone: _onDone,
|
||||
);
|
||||
return _connectionCompleter.future;
|
||||
}
|
||||
@@ -166,7 +164,7 @@ class WebSocket {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info('connection closed | closeCode: ${_channel.closeCode} | '
|
||||
logger?.info('connection closed | closeCode: ${_channel.closeCode} | '
|
||||
'closedReason: ${_channel.closeReason}');
|
||||
|
||||
if (!_reconnecting) {
|
||||
@@ -180,10 +178,10 @@ class WebSocket {
|
||||
}
|
||||
|
||||
final event = _decodeEvent(data);
|
||||
logger.info('received new event: $data');
|
||||
logger?.info('received new event: $data');
|
||||
|
||||
if (_lastEventAt == null) {
|
||||
logger.info('connection estabilished');
|
||||
logger?.info('connection estabilished');
|
||||
_connecting = false;
|
||||
_reconnecting = false;
|
||||
_lastEventAt = DateTime.now();
|
||||
@@ -204,9 +202,9 @@ class WebSocket {
|
||||
}
|
||||
|
||||
Future<void> _onConnectionError(error, [stacktrace]) async {
|
||||
logger..severe('error connecting')..severe(error);
|
||||
logger?..severe('error connecting')..severe(error);
|
||||
if (stacktrace != null) {
|
||||
logger.severe(stacktrace);
|
||||
logger?.severe(stacktrace);
|
||||
}
|
||||
_connecting = false;
|
||||
|
||||
@@ -225,7 +223,7 @@ class WebSocket {
|
||||
void _reconnectionTimer(_) {
|
||||
final now = DateTime.now();
|
||||
if (_lastEventAt != null &&
|
||||
now.difference(_lastEventAt).inSeconds > reconnectionMonitorTimeout) {
|
||||
now.difference(_lastEventAt!).inSeconds > reconnectionMonitorTimeout) {
|
||||
_channel.sink.close();
|
||||
}
|
||||
}
|
||||
@@ -244,18 +242,18 @@ class WebSocket {
|
||||
return;
|
||||
}
|
||||
if (_connecting) {
|
||||
logger.info('already connecting');
|
||||
logger?.info('already connecting');
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info('reconnecting..');
|
||||
logger?.info('reconnecting..');
|
||||
|
||||
_cancelTimers();
|
||||
|
||||
try {
|
||||
await connect();
|
||||
} catch (e) {
|
||||
logger.log(Level.SEVERE, e.toString());
|
||||
logger?.log(Level.SEVERE, e.toString());
|
||||
}
|
||||
await Future.delayed(
|
||||
Duration(seconds: min(_retryAttempt * 5, 25)),
|
||||
@@ -267,7 +265,7 @@ class WebSocket {
|
||||
}
|
||||
|
||||
Future<void> _reconnect() async {
|
||||
logger.info('reconnect');
|
||||
logger?.info('reconnect');
|
||||
if (!_reconnecting) {
|
||||
_reconnecting = true;
|
||||
_connectionStatus = ConnectionStatus.connecting;
|
||||
@@ -279,20 +277,20 @@ class WebSocket {
|
||||
void _cancelTimers() {
|
||||
_lastEventAt = null;
|
||||
if (_healthCheck != null) {
|
||||
_healthCheck.cancel();
|
||||
_healthCheck!.cancel();
|
||||
}
|
||||
if (_reconnectionMonitor != null) {
|
||||
_reconnectionMonitor.cancel();
|
||||
_reconnectionMonitor!.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void _healthCheckTimer(_) {
|
||||
logger.info('sending health.check');
|
||||
logger?.info('sending health.check');
|
||||
_channel.sink.add("{'type': 'health.check'}");
|
||||
}
|
||||
|
||||
void _startHealthCheck() {
|
||||
logger.info('start health check monitor');
|
||||
logger?.info('start health check monitor');
|
||||
|
||||
_healthCheck = Timer.periodic(
|
||||
Duration(seconds: healthCheckInterval),
|
||||
@@ -311,13 +309,13 @@ class WebSocket {
|
||||
if (_manuallyDisconnected) {
|
||||
return;
|
||||
}
|
||||
logger.info('disconnecting');
|
||||
logger?.info('disconnecting');
|
||||
_connectionCompleter = Completer();
|
||||
_cancelTimers();
|
||||
_reconnecting = false;
|
||||
_manuallyDisconnected = true;
|
||||
_connectionStatus = ConnectionStatus.disconnected;
|
||||
await _connectionStatusController.close();
|
||||
return _channel.sink.close();
|
||||
await _channel.sink.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:stream_chat/src/api/responses.dart';
|
||||
import 'package:stream_chat/src/client.dart';
|
||||
import 'package:stream_chat/src/models/attachment_file.dart';
|
||||
import 'package:stream_chat/src/extensions/string_extension.dart';
|
||||
import 'package:stream_chat/src/models/attachment_file.dart';
|
||||
|
||||
/// Class responsible for uploading images and files to a given channel
|
||||
abstract class AttachmentFileUploader {
|
||||
@@ -15,8 +15,8 @@ abstract class AttachmentFileUploader {
|
||||
AttachmentFile image,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
|
||||
/// Uploads a [file] to the given channel.
|
||||
@@ -28,8 +28,8 @@ abstract class AttachmentFileUploader {
|
||||
AttachmentFile file,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
|
||||
/// Deletes a image using its [url] from the given channel.
|
||||
@@ -40,7 +40,7 @@ abstract class AttachmentFileUploader {
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
|
||||
/// Deletes a file using its [url] from the given channel.
|
||||
@@ -51,7 +51,7 @@ abstract class AttachmentFileUploader {
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -67,22 +67,22 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
|
||||
AttachmentFile file,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
final filename = file.path?.split('/')?.last ?? file.name;
|
||||
final mimeType = filename.mimeType;
|
||||
final filename = file.path?.split('/').last ?? file.name;
|
||||
final mimeType = filename?.mimeType;
|
||||
|
||||
MultipartFile multiPartFile;
|
||||
MultipartFile? multiPartFile;
|
||||
if (file.path != null) {
|
||||
multiPartFile = await MultipartFile.fromFile(
|
||||
file.path,
|
||||
file.path!,
|
||||
filename: filename,
|
||||
contentType: mimeType,
|
||||
);
|
||||
} else if (file.bytes != null) {
|
||||
multiPartFile = MultipartFile.fromBytes(
|
||||
file.bytes,
|
||||
file.bytes!,
|
||||
filename: filename,
|
||||
contentType: mimeType,
|
||||
);
|
||||
@@ -104,22 +104,22 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
|
||||
AttachmentFile file,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
final filename = file.path?.split('/')?.last ?? file.name;
|
||||
final mimeType = filename.mimeType;
|
||||
final filename = file.path?.split('/').last ?? file.name;
|
||||
final mimeType = filename?.mimeType;
|
||||
|
||||
MultipartFile multiPartFile;
|
||||
MultipartFile? multiPartFile;
|
||||
if (file.path != null) {
|
||||
multiPartFile = await MultipartFile.fromFile(
|
||||
file.path,
|
||||
file.path!,
|
||||
filename: filename,
|
||||
contentType: mimeType,
|
||||
);
|
||||
} else if (file.bytes != null) {
|
||||
multiPartFile = MultipartFile.fromBytes(
|
||||
file.bytes,
|
||||
file.bytes!,
|
||||
filename: filename,
|
||||
contentType: mimeType,
|
||||
);
|
||||
@@ -141,7 +141,7 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
final response = await _client.delete(
|
||||
'/channels/$channelType/$channelId/image',
|
||||
@@ -156,7 +156,7 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
final response = await _client.delete(
|
||||
'/channels/$channelType/$channelId/file',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,11 +2,13 @@ import 'package:stream_chat/src/api/requests.dart';
|
||||
import 'package:stream_chat/src/models/channel_model.dart';
|
||||
import 'package:stream_chat/src/models/channel_state.dart';
|
||||
import 'package:stream_chat/src/models/event.dart';
|
||||
import 'package:stream_chat/src/models/filter.dart';
|
||||
import 'package:stream_chat/src/models/member.dart';
|
||||
import 'package:stream_chat/src/models/message.dart';
|
||||
import 'package:stream_chat/src/models/reaction.dart';
|
||||
import 'package:stream_chat/src/models/read.dart';
|
||||
import 'package:stream_chat/src/models/user.dart';
|
||||
import 'package:stream_chat/src/extensions/iterable_extension.dart';
|
||||
|
||||
/// A simple client used for persisting chat data locally.
|
||||
abstract class ChatPersistenceClient {
|
||||
@@ -20,14 +22,14 @@ abstract class ChatPersistenceClient {
|
||||
/// Get stored replies by messageId
|
||||
Future<List<Message>> getReplies(
|
||||
String parentId, {
|
||||
PaginationParams options,
|
||||
PaginationParams? options,
|
||||
});
|
||||
|
||||
/// Get stored connection event
|
||||
Future<Event> getConnectionInfo();
|
||||
Future<Event?> getConnectionInfo();
|
||||
|
||||
/// Get stored lastSyncAt
|
||||
Future<DateTime> getLastSyncAt();
|
||||
Future<DateTime?> getLastSyncAt();
|
||||
|
||||
/// Update stored connection event
|
||||
Future<void> updateConnectionInfo(Event event);
|
||||
@@ -39,7 +41,7 @@ abstract class ChatPersistenceClient {
|
||||
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);
|
||||
@@ -53,20 +55,20 @@ abstract class ChatPersistenceClient {
|
||||
/// for filtering out messages
|
||||
Future<List<Message>> getMessagesByCid(
|
||||
String cid, {
|
||||
PaginationParams messagePagination,
|
||||
PaginationParams? messagePagination,
|
||||
});
|
||||
|
||||
/// Get stored pinned [Message]s by providing channel [cid]
|
||||
Future<List<Message>> getPinnedMessagesByCid(
|
||||
String cid, {
|
||||
PaginationParams messagePagination,
|
||||
PaginationParams? messagePagination,
|
||||
});
|
||||
|
||||
/// Get [ChannelState] data by providing channel [cid]
|
||||
Future<ChannelState> getChannelStateByCid(
|
||||
String cid, {
|
||||
PaginationParams messagePagination,
|
||||
PaginationParams pinnedMessagePagination,
|
||||
PaginationParams? messagePagination,
|
||||
PaginationParams? pinnedMessagePagination,
|
||||
}) async {
|
||||
final data = await Future.wait([
|
||||
getMembersByCid(cid),
|
||||
@@ -76,11 +78,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 +91,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,
|
||||
Filter? filter,
|
||||
List<SortOption<ChannelModel>>? sort,
|
||||
PaginationParams? paginationParams,
|
||||
});
|
||||
|
||||
/// Update list of channel queries.
|
||||
@@ -99,7 +101,7 @@ 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,
|
||||
Filter? filter,
|
||||
List<String> cids, {
|
||||
bool clearQueryCache = false,
|
||||
});
|
||||
@@ -180,8 +182,11 @@ abstract class ChatPersistenceClient {
|
||||
.map((m) => m.id)
|
||||
.toList(growable: false));
|
||||
|
||||
final cleanedChannelStates =
|
||||
channelStates.where((it) => it.channel != null);
|
||||
|
||||
final deleteMembers = deleteMembersByCids(
|
||||
channelStates.map((it) => it.channel.cid).toList(growable: false),
|
||||
cleanedChannelStates.map((it) => it.channel!.cid).toList(growable: false),
|
||||
);
|
||||
|
||||
await Future.wait([
|
||||
@@ -189,58 +194,57 @@ abstract class ChatPersistenceClient {
|
||||
deleteMembers,
|
||||
]);
|
||||
|
||||
final channels =
|
||||
channelStates.map((it) => it.channel).where((it) => it != null);
|
||||
final channels = cleanedChannelStates.map((it) => it.channel).withNullifyer;
|
||||
|
||||
final reactions = channelStates
|
||||
final reactions = cleanedChannelStates
|
||||
.expand((it) => it.messages)
|
||||
.expand((it) => [
|
||||
if (it.ownReactions != null)
|
||||
...it.ownReactions.where((r) => r.userId != null),
|
||||
...it.ownReactions!.where((r) => r.userId != null),
|
||||
if (it.latestReactions != null)
|
||||
...it.latestReactions.where((r) => r.userId != null)
|
||||
...it.latestReactions!.where((r) => r.userId != null),
|
||||
])
|
||||
.where((it) => it != null);
|
||||
.withNullifyer;
|
||||
|
||||
final users = channelStates
|
||||
final users = cleanedChannelStates
|
||||
.map((cs) => [
|
||||
cs.channel?.createdBy,
|
||||
...cs.messages
|
||||
?.map((m) => [
|
||||
.map((m) => [
|
||||
m.user,
|
||||
if (m.latestReactions != null)
|
||||
...m.latestReactions.map((r) => r.user),
|
||||
...m.latestReactions!.map((r) => r.user),
|
||||
if (m.ownReactions != null)
|
||||
...m.ownReactions.map((r) => r.user),
|
||||
...m.ownReactions!.map((r) => r.user),
|
||||
])
|
||||
?.expand((v) => v),
|
||||
if (cs.read != null) ...cs.read.map((r) => r.user),
|
||||
if (cs.members != null) ...cs.members.map((m) => m.user),
|
||||
.expand((v) => v),
|
||||
...cs.read.map((r) => r.user),
|
||||
...cs.members.map((m) => m.user),
|
||||
])
|
||||
.expand((it) => it)
|
||||
.where((it) => it != null);
|
||||
.withNullifyer;
|
||||
|
||||
final updateMessagesFuture = channelStates.map((it) {
|
||||
final cid = it.channel.cid;
|
||||
final messages = it.messages.where((it) => it != null);
|
||||
final updateMessagesFuture = cleanedChannelStates.map((it) {
|
||||
final cid = it.channel!.cid;
|
||||
final messages = it.messages;
|
||||
return updateMessages(cid, messages.toList(growable: false));
|
||||
}).toList(growable: false);
|
||||
|
||||
final updatePinnedMessagesFuture = channelStates.map((it) {
|
||||
final cid = it.channel.cid;
|
||||
final messages = it.pinnedMessages.where((it) => it != null);
|
||||
final updatePinnedMessagesFuture = cleanedChannelStates.map((it) {
|
||||
final cid = it.channel!.cid;
|
||||
final messages = it.pinnedMessages;
|
||||
return updatePinnedMessages(cid, messages.toList(growable: false));
|
||||
}).toList(growable: false);
|
||||
|
||||
final updateReadsFuture = channelStates.map((it) {
|
||||
final cid = it.channel.cid;
|
||||
final reads = it.read?.where((it) => it != null) ?? [];
|
||||
final updateReadsFuture = cleanedChannelStates.map((it) {
|
||||
final cid = it.channel!.cid;
|
||||
final reads = it.read;
|
||||
return updateReads(cid, reads.toList(growable: false));
|
||||
}).toList(growable: false);
|
||||
|
||||
final updateMembersFuture = channelStates.map((it) {
|
||||
final cid = it.channel.cid;
|
||||
final members = it.members.where((it) => it != null);
|
||||
final updateMembersFuture = cleanedChannelStates.map((it) {
|
||||
final cid = it.channel!.cid;
|
||||
final members = it.members;
|
||||
return updateMembers(cid, members.toList(growable: false));
|
||||
}).toList(growable: false);
|
||||
|
||||
|
||||
@@ -4,25 +4,25 @@ import 'dart:convert';
|
||||
class ApiError extends Error {
|
||||
/// Creates a new ApiError instance using the response body and status code
|
||||
ApiError(this.body, this.status) : jsonData = _decode(body) {
|
||||
if (jsonData != null && jsonData.containsKey('code')) {
|
||||
_code = jsonData['code'];
|
||||
if (jsonData != null && jsonData!.containsKey('code')) {
|
||||
_code = jsonData!['code'];
|
||||
}
|
||||
}
|
||||
|
||||
/// Raw body of the response
|
||||
final String body;
|
||||
final String? body;
|
||||
|
||||
/// Json parsed body
|
||||
final Map<String, dynamic> jsonData;
|
||||
final Map<String, dynamic>? jsonData;
|
||||
|
||||
/// Http status code of the response
|
||||
final int status;
|
||||
final int? status;
|
||||
|
||||
/// Stream specific error code
|
||||
int get code => _code;
|
||||
int _code;
|
||||
int? get code => _code;
|
||||
int? _code;
|
||||
|
||||
static Map<String, dynamic> _decode(String body) {
|
||||
static Map<String, dynamic>? _decode(String? body) {
|
||||
try {
|
||||
if (body == null) {
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/// Useful extension functions for [Iterable]
|
||||
extension IterableX<T> on Iterable<T?> {
|
||||
/// Removes all the null values
|
||||
/// and converts `Iterable<T?>` into `Iterable<T>`
|
||||
Iterable<T> get withNullifyer => [
|
||||
for (final item in this)
|
||||
if (item != null) item
|
||||
];
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/// Useful extension functions for [Map]
|
||||
extension MapX on Map {
|
||||
extension MapX<K, V> on Map<K, V> {
|
||||
/// Returns a new map with null keys or values removed
|
||||
Map<String, dynamic> get nullProtected =>
|
||||
{...this}..removeWhere((key, value) => key == null || value == null);
|
||||
Map<K, V> get nullProtected =>
|
||||
Map.from(this)..removeWhere((key, value) => key == null || value == null);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ extension RateLimit on Function {
|
||||
Duration wait, {
|
||||
bool leading = false,
|
||||
bool trailing = true,
|
||||
Duration maxWait,
|
||||
Duration? maxWait,
|
||||
}) =>
|
||||
Debounce(
|
||||
this,
|
||||
@@ -40,7 +40,7 @@ Debounce debounce(
|
||||
Duration wait, {
|
||||
bool leading = false,
|
||||
bool trailing = true,
|
||||
Duration maxWait,
|
||||
Duration? maxWait,
|
||||
}) =>
|
||||
Debounce(
|
||||
func,
|
||||
@@ -121,13 +121,13 @@ class Debounce {
|
||||
Duration wait, {
|
||||
bool leading = false,
|
||||
bool trailing = true,
|
||||
Duration maxWait,
|
||||
Duration? maxWait,
|
||||
}) : _leading = leading,
|
||||
_trailing = trailing,
|
||||
_wait = wait?.inMilliseconds ?? 0,
|
||||
_wait = wait.inMilliseconds,
|
||||
_maxing = maxWait != null {
|
||||
if (_maxing) {
|
||||
_maxWait = math.max(maxWait.inMilliseconds, _wait);
|
||||
_maxWait = math.max(maxWait!.inMilliseconds, _wait);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,15 +137,15 @@ class Debounce {
|
||||
final int _wait;
|
||||
final bool _maxing;
|
||||
|
||||
int _maxWait;
|
||||
List<Object> _lastArgs;
|
||||
Map<Symbol, Object> _lastNamedArgs;
|
||||
Timer _timer;
|
||||
int _lastCallTime;
|
||||
Object _result;
|
||||
int _lastInvokeTime = 0;
|
||||
late int _maxWait;
|
||||
List<Object?>? _lastArgs;
|
||||
Map<Symbol, Object>? _lastNamedArgs;
|
||||
Timer? _timer;
|
||||
int? _lastCallTime;
|
||||
Object? _result;
|
||||
int? _lastInvokeTime = 0;
|
||||
|
||||
Object _invokeFunc(int time) {
|
||||
Object? _invokeFunc(int? time) {
|
||||
final args = _lastArgs;
|
||||
final namedArgs = _lastNamedArgs;
|
||||
_lastArgs = _lastNamedArgs = null;
|
||||
@@ -154,11 +154,11 @@ class Debounce {
|
||||
}
|
||||
|
||||
Timer _startTimer(Function pendingFunc, int wait) =>
|
||||
Timer(Duration(milliseconds: wait), pendingFunc);
|
||||
Timer(Duration(milliseconds: wait), pendingFunc as void Function());
|
||||
|
||||
bool _shouldInvoke(int time) {
|
||||
final timeSinceLastCall = time - (_lastCallTime ?? double.nan);
|
||||
final timeSinceLastInvoke = time - _lastInvokeTime;
|
||||
final timeSinceLastInvoke = time - _lastInvokeTime!;
|
||||
|
||||
// Either this is the first call, activity has stopped and we're at the
|
||||
// trailing edge, the system time has gone backwards and we're treating
|
||||
@@ -169,7 +169,7 @@ class Debounce {
|
||||
(_maxing && timeSinceLastInvoke >= _maxWait);
|
||||
}
|
||||
|
||||
Object _trailingEdge(int time) {
|
||||
Object? _trailingEdge(int time) {
|
||||
_timer = null;
|
||||
|
||||
// Only invoke if we have `lastArgs` which means `func` has been
|
||||
@@ -182,8 +182,8 @@ class Debounce {
|
||||
}
|
||||
|
||||
int _remainingWait(int time) {
|
||||
final timeSinceLastCall = time - _lastCallTime;
|
||||
final timeSinceLastInvoke = time - _lastInvokeTime;
|
||||
final timeSinceLastCall = time - _lastCallTime!;
|
||||
final timeSinceLastInvoke = time - _lastInvokeTime!;
|
||||
final timeWaiting = _wait - timeSinceLastCall;
|
||||
|
||||
return _maxing
|
||||
@@ -201,7 +201,7 @@ class Debounce {
|
||||
}
|
||||
}
|
||||
|
||||
Object _leadingEdge(int time) {
|
||||
Object? _leadingEdge(int? time) {
|
||||
// Reset any `maxWait` timer.
|
||||
_lastInvokeTime = time;
|
||||
// Start the timer for the trailing edge.
|
||||
@@ -218,7 +218,7 @@ class Debounce {
|
||||
}
|
||||
|
||||
/// Immediately invokes all the remaining delayed functions.
|
||||
Object flush() {
|
||||
Object? flush() {
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
return _timer == null ? _result : _trailingEdge(now);
|
||||
}
|
||||
@@ -228,15 +228,15 @@ class Debounce {
|
||||
|
||||
/// Calls/invokes this class like a function.
|
||||
/// Pass [args] and [namedArgs] to be used while invoking [_func].
|
||||
Object call(
|
||||
Object? call(
|
||||
List<dynamic> args, {
|
||||
Map<Symbol, dynamic> namedArgs,
|
||||
Map<Symbol, dynamic>? namedArgs,
|
||||
}) {
|
||||
final time = DateTime.now().millisecondsSinceEpoch;
|
||||
final isInvoking = _shouldInvoke(time);
|
||||
|
||||
_lastArgs = args;
|
||||
_lastNamedArgs = namedArgs;
|
||||
_lastNamedArgs = namedArgs as Map<Symbol, Object>?;
|
||||
_lastCallTime = time;
|
||||
|
||||
if (isInvoking) {
|
||||
@@ -323,13 +323,13 @@ class Throttle {
|
||||
void cancel() => _debounce.cancel();
|
||||
|
||||
/// Immediately invokes all the remaining delayed functions.
|
||||
Object flush() => _debounce.flush();
|
||||
Object? flush() => _debounce.flush();
|
||||
|
||||
/// True if there are functions remaining to get invoked.
|
||||
bool get isPending => _debounce.isPending;
|
||||
|
||||
/// Calls/invokes this class like a function.
|
||||
/// Pass [args] and [namedArgs] to be used while invoking `func`.
|
||||
Object call(List<dynamic> args, {Map<Symbol, dynamic> namedArgs}) =>
|
||||
Object? call(List<dynamic> args, {Map<Symbol, dynamic>? namedArgs}) =>
|
||||
_debounce.call(args, namedArgs: namedArgs);
|
||||
}
|
||||
|
||||
@@ -4,12 +4,15 @@ import 'package:mime/mime.dart';
|
||||
/// Useful extension functions for [String]
|
||||
extension StringX on String {
|
||||
/// Returns the mime type from the passed file name.
|
||||
http_parser.MediaType get mimeType {
|
||||
if (this == null) return null;
|
||||
http_parser.MediaType? get mimeType {
|
||||
if (toLowerCase().endsWith('heic')) {
|
||||
return http_parser.MediaType.parse('image/heic');
|
||||
} else {
|
||||
return http_parser.MediaType.parse(lookupMimeType(this));
|
||||
final mimeType = lookupMimeType(this);
|
||||
if (mimeType == null) {
|
||||
return null;
|
||||
}
|
||||
return http_parser.MediaType.parse(mimeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,13 @@ part 'action.g.dart';
|
||||
@JsonSerializable()
|
||||
class Action {
|
||||
/// Constructor used for json serialization
|
||||
Action({this.name, this.style, this.text, this.type, this.value});
|
||||
Action({
|
||||
required this.name,
|
||||
this.style = 'default',
|
||||
required this.text,
|
||||
required this.type,
|
||||
this.value,
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Action.fromJson(Map<String, dynamic> json) => _$ActionFromJson(json);
|
||||
@@ -15,6 +21,7 @@ class Action {
|
||||
final String name;
|
||||
|
||||
/// The style of the action
|
||||
@JsonKey(defaultValue: 'default')
|
||||
final String style;
|
||||
|
||||
/// The test of the action
|
||||
@@ -24,7 +31,7 @@ class Action {
|
||||
final String type;
|
||||
|
||||
/// The value of the action
|
||||
final String value;
|
||||
final String? value;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => _$ActionToJson(this);
|
||||
|
||||
@@ -6,13 +6,13 @@ part of 'action.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Action _$ActionFromJson(Map json) {
|
||||
Action _$ActionFromJson(Map<String, dynamic> json) {
|
||||
return Action(
|
||||
name: json['name'] as String,
|
||||
style: json['style'] as String,
|
||||
style: json['style'] as String? ?? 'default',
|
||||
text: json['text'] as String,
|
||||
type: json['type'] as String,
|
||||
value: json['value'] as String,
|
||||
value: json['value'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,10 @@ part 'attachment.g.dart';
|
||||
class Attachment extends Equatable {
|
||||
/// Constructor used for json serialization
|
||||
Attachment({
|
||||
String id,
|
||||
String? id,
|
||||
this.type,
|
||||
this.titleLink,
|
||||
String title,
|
||||
String? title,
|
||||
this.thumbUrl,
|
||||
this.text,
|
||||
this.pretext,
|
||||
@@ -32,17 +32,19 @@ class Attachment extends Equatable {
|
||||
this.authorLink,
|
||||
this.authorIcon,
|
||||
this.assetUrl,
|
||||
this.actions,
|
||||
this.extraData,
|
||||
List<Action>? actions,
|
||||
this.extraData = const {},
|
||||
this.file,
|
||||
UploadState uploadState,
|
||||
}) : id = id ?? Uuid().v4(),
|
||||
UploadState? uploadState,
|
||||
}) : id = id ?? const Uuid().v4(),
|
||||
title = title ?? file?.name,
|
||||
localUri = file?.path != null ? Uri.parse(file.path) : null,
|
||||
uploadState = uploadState ??
|
||||
((assetUrl != null || imageUrl != null)
|
||||
? const UploadState.success()
|
||||
: const UploadState.preparing());
|
||||
localUri = file?.path != null ? Uri.parse(file!.path!) : null,
|
||||
actions = actions ?? [] {
|
||||
this.uploadState = uploadState ??
|
||||
((assetUrl != null || imageUrl != null)
|
||||
? const UploadState.success()
|
||||
: const UploadState.preparing());
|
||||
}
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Attachment.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -56,59 +58,63 @@ class Attachment extends Equatable {
|
||||
|
||||
///The attachment type based on the URL resource. This can be: audio,
|
||||
///image or video
|
||||
final String type;
|
||||
final String? type;
|
||||
|
||||
///The link to which the attachment message points to.
|
||||
final String titleLink;
|
||||
final String? titleLink;
|
||||
|
||||
/// The attachment title
|
||||
final String title;
|
||||
final String? title;
|
||||
|
||||
/// The URL to the attached file thumbnail. You can use this to represent the
|
||||
/// attached link.
|
||||
final String thumbUrl;
|
||||
final String? thumbUrl;
|
||||
|
||||
/// The attachment text. It will be displayed in the channel next to the
|
||||
/// original message.
|
||||
final String text;
|
||||
final String? text;
|
||||
|
||||
/// Optional text that appears above the attachment block
|
||||
final String pretext;
|
||||
final String? pretext;
|
||||
|
||||
/// The original URL that was used to scrape this attachment.
|
||||
final String ogScrapeUrl;
|
||||
final String? ogScrapeUrl;
|
||||
|
||||
/// The URL to the attached image. This is present for URL pointing to an
|
||||
/// image article (eg. Unsplash)
|
||||
final String imageUrl;
|
||||
final String footerIcon;
|
||||
final String footer;
|
||||
final String? imageUrl;
|
||||
final String? footerIcon;
|
||||
final String? footer;
|
||||
final dynamic fields;
|
||||
final String fallback;
|
||||
final String color;
|
||||
final String? fallback;
|
||||
final String? color;
|
||||
|
||||
/// The name of the author.
|
||||
final String authorName;
|
||||
final String authorLink;
|
||||
final String authorIcon;
|
||||
final String? authorName;
|
||||
final String? authorLink;
|
||||
final String? authorIcon;
|
||||
|
||||
/// The URL to the audio, video or image related to the URL.
|
||||
final String assetUrl;
|
||||
final String? assetUrl;
|
||||
|
||||
/// Actions from a command
|
||||
@JsonKey(defaultValue: [])
|
||||
final List<Action> actions;
|
||||
|
||||
final Uri localUri;
|
||||
final Uri? localUri;
|
||||
|
||||
/// The file present inside this attachment.
|
||||
final AttachmentFile file;
|
||||
final AttachmentFile? file;
|
||||
|
||||
/// The current upload state of the attachment
|
||||
final UploadState uploadState;
|
||||
late final UploadState uploadState;
|
||||
|
||||
/// Map of custom channel extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, dynamic> extraData;
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
defaultValue: {},
|
||||
)
|
||||
final Map<String, Object> extraData;
|
||||
|
||||
/// The attachment ID.
|
||||
///
|
||||
@@ -147,37 +153,37 @@ class Attachment extends Equatable {
|
||||
];
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$AttachmentToJson(this), topLevelFields)
|
||||
..removeWhere((key, value) => dbSpecificTopLevelFields.contains(key));
|
||||
Map<String, dynamic> toJson() =>
|
||||
Serialization.moveFromExtraDataToRoot(_$AttachmentToJson(this))
|
||||
..removeWhere((key, value) => dbSpecificTopLevelFields.contains(key));
|
||||
|
||||
/// Serialize to db data
|
||||
Map<String, dynamic> toData() => Serialization.moveFromExtraDataToRoot(
|
||||
_$AttachmentToJson(this), topLevelFields + dbSpecificTopLevelFields);
|
||||
Map<String, dynamic> toData() =>
|
||||
Serialization.moveFromExtraDataToRoot(_$AttachmentToJson(this));
|
||||
|
||||
Attachment copyWith({
|
||||
String id,
|
||||
String type,
|
||||
String titleLink,
|
||||
String title,
|
||||
String thumbUrl,
|
||||
String text,
|
||||
String pretext,
|
||||
String ogScrapeUrl,
|
||||
String imageUrl,
|
||||
String footerIcon,
|
||||
String footer,
|
||||
String? id,
|
||||
String? type,
|
||||
String? titleLink,
|
||||
String? title,
|
||||
String? thumbUrl,
|
||||
String? text,
|
||||
String? pretext,
|
||||
String? ogScrapeUrl,
|
||||
String? imageUrl,
|
||||
String? footerIcon,
|
||||
String? footer,
|
||||
dynamic fields,
|
||||
String fallback,
|
||||
String color,
|
||||
String authorName,
|
||||
String authorLink,
|
||||
String authorIcon,
|
||||
String assetUrl,
|
||||
List<Action> actions,
|
||||
AttachmentFile file,
|
||||
UploadState uploadState,
|
||||
Map<String, dynamic> extraData,
|
||||
String? fallback,
|
||||
String? color,
|
||||
String? authorName,
|
||||
String? authorLink,
|
||||
String? authorIcon,
|
||||
String? assetUrl,
|
||||
List<Action>? actions,
|
||||
AttachmentFile? file,
|
||||
UploadState? uploadState,
|
||||
Map<String, Object>? extraData,
|
||||
}) =>
|
||||
Attachment(
|
||||
id: id ?? this.id,
|
||||
@@ -205,7 +211,7 @@ class Attachment extends Equatable {
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
type,
|
||||
titleLink,
|
||||
|
||||
@@ -6,46 +6,40 @@ part of 'attachment.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Attachment _$AttachmentFromJson(Map json) {
|
||||
Attachment _$AttachmentFromJson(Map<String, dynamic> json) {
|
||||
return Attachment(
|
||||
id: json['id'] as String,
|
||||
type: json['type'] as String,
|
||||
titleLink: json['title_link'] as String,
|
||||
title: json['title'] as String,
|
||||
thumbUrl: json['thumb_url'] as String,
|
||||
text: json['text'] as String,
|
||||
pretext: json['pretext'] as String,
|
||||
ogScrapeUrl: json['og_scrape_url'] as String,
|
||||
imageUrl: json['image_url'] as String,
|
||||
footerIcon: json['footer_icon'] as String,
|
||||
footer: json['footer'] as String,
|
||||
id: json['id'] as String?,
|
||||
type: json['type'] as String?,
|
||||
titleLink: json['title_link'] as String?,
|
||||
title: json['title'] as String?,
|
||||
thumbUrl: json['thumb_url'] as String?,
|
||||
text: json['text'] as String?,
|
||||
pretext: json['pretext'] as String?,
|
||||
ogScrapeUrl: json['og_scrape_url'] as String?,
|
||||
imageUrl: json['image_url'] as String?,
|
||||
footerIcon: json['footer_icon'] as String?,
|
||||
footer: json['footer'] as String?,
|
||||
fields: json['fields'],
|
||||
fallback: json['fallback'] as String,
|
||||
color: json['color'] as String,
|
||||
authorName: json['author_name'] as String,
|
||||
authorLink: json['author_link'] as String,
|
||||
authorIcon: json['author_icon'] as String,
|
||||
assetUrl: json['asset_url'] as String,
|
||||
actions: (json['actions'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Action.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
),
|
||||
fallback: json['fallback'] as String?,
|
||||
color: json['color'] as String?,
|
||||
authorName: json['author_name'] as String?,
|
||||
authorLink: json['author_link'] as String?,
|
||||
authorIcon: json['author_icon'] as String?,
|
||||
assetUrl: json['asset_url'] as String?,
|
||||
actions: (json['actions'] as List<dynamic>?)
|
||||
?.map((e) => Action.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
extraData: (json['extra_data'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, e as Object),
|
||||
) ??
|
||||
{},
|
||||
file: json['file'] == null
|
||||
? null
|
||||
: AttachmentFile.fromJson((json['file'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: AttachmentFile.fromJson(json['file'] as Map<String, dynamic>),
|
||||
uploadState: json['upload_state'] == null
|
||||
? null
|
||||
: UploadState.fromJson((json['upload_state'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: UploadState.fromJson(json['upload_state'] as Map<String, dynamic>),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -75,10 +69,10 @@ Map<String, dynamic> _$AttachmentToJson(Attachment instance) {
|
||||
writeNotNull('author_link', instance.authorLink);
|
||||
writeNotNull('author_icon', instance.authorIcon);
|
||||
writeNotNull('asset_url', instance.assetUrl);
|
||||
writeNotNull('actions', instance.actions?.map((e) => e?.toJson())?.toList());
|
||||
val['actions'] = instance.actions.map((e) => e.toJson()).toList();
|
||||
writeNotNull('file', instance.file?.toJson());
|
||||
writeNotNull('upload_state', instance.uploadState?.toJson());
|
||||
writeNotNull('extra_data', instance.extraData);
|
||||
writeNotNull('id', instance.id);
|
||||
val['upload_state'] = instance.uploadState.toJson();
|
||||
val['extra_data'] = instance.extraData;
|
||||
val['id'] = instance.id;
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -8,18 +8,21 @@ part 'attachment_file.g.dart';
|
||||
|
||||
/// Union class to hold various [UploadState] of a attachment.
|
||||
@freezed
|
||||
abstract class UploadState with _$UploadState {
|
||||
class UploadState with _$UploadState {
|
||||
/// Preparing state of the union
|
||||
const factory UploadState.preparing() = Preparing;
|
||||
|
||||
/// InProgress state of the union
|
||||
const factory UploadState.inProgress({int uploaded, int total}) = InProgress;
|
||||
const factory UploadState.inProgress({
|
||||
required int uploaded,
|
||||
required int total,
|
||||
}) = InProgress;
|
||||
|
||||
/// Success state of the union
|
||||
const factory UploadState.success() = Success;
|
||||
|
||||
/// Failed state of the union
|
||||
const factory UploadState.failed({@required String error}) = Failed;
|
||||
const factory UploadState.failed({required String error}) = Failed;
|
||||
|
||||
/// Creates a new instance from a json
|
||||
factory UploadState.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -27,7 +30,7 @@ abstract class UploadState with _$UploadState {
|
||||
}
|
||||
|
||||
/// Helper extension for UploadState
|
||||
extension UploadStateX on UploadState {
|
||||
extension UploadStateX on UploadState? {
|
||||
/// Returns true if state is [Preparing]
|
||||
bool get isPreparing => this is Preparing;
|
||||
|
||||
@@ -41,20 +44,29 @@ extension UploadStateX on UploadState {
|
||||
bool get isFailed => this is Failed;
|
||||
}
|
||||
|
||||
Uint8List _fromString(String bytes) => Uint8List.fromList(bytes.codeUnits);
|
||||
Uint8List? _fromString(String? bytes) {
|
||||
if (bytes == null) return null;
|
||||
return Uint8List.fromList(bytes.codeUnits);
|
||||
}
|
||||
|
||||
String _toString(Uint8List bytes) => String.fromCharCodes(bytes);
|
||||
String? _toString(Uint8List? bytes) {
|
||||
if (bytes == null) return null;
|
||||
return String.fromCharCodes(bytes);
|
||||
}
|
||||
|
||||
/// The class that contains the information about an attachment file
|
||||
@JsonSerializable()
|
||||
class AttachmentFile {
|
||||
/// Creates a new [AttachmentFile] instance.
|
||||
const AttachmentFile({
|
||||
required this.size,
|
||||
this.path,
|
||||
this.name,
|
||||
this.bytes,
|
||||
this.size,
|
||||
});
|
||||
}) : assert(
|
||||
path != null || bytes != null,
|
||||
'Either path or bytes should be != null',
|
||||
);
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory AttachmentFile.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -65,21 +77,21 @@ class AttachmentFile {
|
||||
/// ```
|
||||
/// final File myFile = File(platformFile.path);
|
||||
/// ```
|
||||
final String path;
|
||||
final String? path;
|
||||
|
||||
/// File name including its extension.
|
||||
final String name;
|
||||
final String? name;
|
||||
|
||||
/// Byte data for this file. Particularly useful if you want to manipulate
|
||||
/// its data or easily upload to somewhere else.
|
||||
@JsonKey(toJson: _toString, fromJson: _fromString)
|
||||
final Uint8List bytes;
|
||||
final Uint8List? bytes;
|
||||
|
||||
/// The file size in bytes.
|
||||
final int size;
|
||||
final int? size;
|
||||
|
||||
/// File extension for this file.
|
||||
String get extension => name?.split('.')?.last;
|
||||
String? get extension => name?.split('.').last;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => _$AttachmentFileToJson(this);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides
|
||||
|
||||
part of 'attachment_file.dart';
|
||||
|
||||
@@ -8,6 +8,10 @@ part of 'attachment_file.dart';
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||
|
||||
UploadState _$UploadStateFromJson(Map<String, dynamic> json) {
|
||||
switch (json['runtimeType'] as String) {
|
||||
case 'preparing':
|
||||
@@ -28,74 +32,72 @@ UploadState _$UploadStateFromJson(Map<String, dynamic> json) {
|
||||
class _$UploadStateTearOff {
|
||||
const _$UploadStateTearOff();
|
||||
|
||||
// ignore: unused_element
|
||||
Preparing preparing() {
|
||||
return const Preparing();
|
||||
}
|
||||
|
||||
// ignore: unused_element
|
||||
InProgress inProgress({int uploaded, int total}) {
|
||||
InProgress inProgress({required int uploaded, required int total}) {
|
||||
return InProgress(
|
||||
uploaded: uploaded,
|
||||
total: total,
|
||||
);
|
||||
}
|
||||
|
||||
// ignore: unused_element
|
||||
Success success() {
|
||||
return const Success();
|
||||
}
|
||||
|
||||
// ignore: unused_element
|
||||
Failed failed({@required String error}) {
|
||||
Failed failed({required String error}) {
|
||||
return Failed(
|
||||
error: error,
|
||||
);
|
||||
}
|
||||
|
||||
// ignore: unused_element
|
||||
UploadState fromJson(Map<String, Object> json) {
|
||||
return UploadState.fromJson(json);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
// ignore: unused_element
|
||||
const $UploadState = _$UploadStateTearOff();
|
||||
|
||||
/// @nodoc
|
||||
mixin _$UploadState {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object>({
|
||||
@required TResult preparing(),
|
||||
@required TResult inProgress(int uploaded, int total),
|
||||
@required TResult success(),
|
||||
@required TResult failed(String error),
|
||||
});
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() preparing,
|
||||
required TResult Function(int uploaded, int total) inProgress,
|
||||
required TResult Function() success,
|
||||
required TResult Function(String error) failed,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object>({
|
||||
TResult preparing(),
|
||||
TResult inProgress(int uploaded, int total),
|
||||
TResult success(),
|
||||
TResult failed(String error),
|
||||
@required TResult orElse(),
|
||||
});
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object>({
|
||||
@required TResult preparing(Preparing value),
|
||||
@required TResult inProgress(InProgress value),
|
||||
@required TResult success(Success value),
|
||||
@required TResult failed(Failed value),
|
||||
});
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Preparing value) preparing,
|
||||
required TResult Function(InProgress value) inProgress,
|
||||
required TResult Function(Success value) success,
|
||||
required TResult Function(Failed value) failed,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object>({
|
||||
TResult preparing(Preparing value),
|
||||
TResult inProgress(InProgress value),
|
||||
TResult success(Success value),
|
||||
TResult failed(Failed value),
|
||||
@required TResult orElse(),
|
||||
});
|
||||
Map<String, dynamic> toJson();
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -154,29 +156,24 @@ class _$Preparing implements Preparing {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object>({
|
||||
@required TResult preparing(),
|
||||
@required TResult inProgress(int uploaded, int total),
|
||||
@required TResult success(),
|
||||
@required TResult failed(String error),
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() preparing,
|
||||
required TResult Function(int uploaded, int total) inProgress,
|
||||
required TResult Function() success,
|
||||
required TResult Function(String error) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return preparing();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object>({
|
||||
TResult preparing(),
|
||||
TResult inProgress(int uploaded, int total),
|
||||
TResult success(),
|
||||
TResult failed(String error),
|
||||
@required TResult orElse(),
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (preparing != null) {
|
||||
return preparing();
|
||||
}
|
||||
@@ -185,29 +182,24 @@ class _$Preparing implements Preparing {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object>({
|
||||
@required TResult preparing(Preparing value),
|
||||
@required TResult inProgress(InProgress value),
|
||||
@required TResult success(Success value),
|
||||
@required TResult failed(Failed value),
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Preparing value) preparing,
|
||||
required TResult Function(InProgress value) inProgress,
|
||||
required TResult Function(Success value) success,
|
||||
required TResult Function(Failed value) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return preparing(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object>({
|
||||
TResult preparing(Preparing value),
|
||||
TResult inProgress(InProgress value),
|
||||
TResult success(Success value),
|
||||
TResult failed(Failed value),
|
||||
@required TResult orElse(),
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (preparing != null) {
|
||||
return preparing(this);
|
||||
}
|
||||
@@ -245,12 +237,18 @@ class _$InProgressCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res>
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object uploaded = freezed,
|
||||
Object total = freezed,
|
||||
Object? uploaded = freezed,
|
||||
Object? total = freezed,
|
||||
}) {
|
||||
return _then(InProgress(
|
||||
uploaded: uploaded == freezed ? _value.uploaded : uploaded as int,
|
||||
total: total == freezed ? _value.total : total as int,
|
||||
uploaded: uploaded == freezed
|
||||
? _value.uploaded
|
||||
: uploaded // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
total: total == freezed
|
||||
? _value.total
|
||||
: total // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -259,7 +257,7 @@ class _$InProgressCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res>
|
||||
|
||||
/// @nodoc
|
||||
class _$InProgress implements InProgress {
|
||||
const _$InProgress({this.uploaded, this.total});
|
||||
const _$InProgress({required this.uploaded, required this.total});
|
||||
|
||||
factory _$InProgress.fromJson(Map<String, dynamic> json) =>
|
||||
_$_$InProgressFromJson(json);
|
||||
@@ -298,29 +296,24 @@ class _$InProgress implements InProgress {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object>({
|
||||
@required TResult preparing(),
|
||||
@required TResult inProgress(int uploaded, int total),
|
||||
@required TResult success(),
|
||||
@required TResult failed(String error),
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() preparing,
|
||||
required TResult Function(int uploaded, int total) inProgress,
|
||||
required TResult Function() success,
|
||||
required TResult Function(String error) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return inProgress(uploaded, total);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object>({
|
||||
TResult preparing(),
|
||||
TResult inProgress(int uploaded, int total),
|
||||
TResult success(),
|
||||
TResult failed(String error),
|
||||
@required TResult orElse(),
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (inProgress != null) {
|
||||
return inProgress(uploaded, total);
|
||||
}
|
||||
@@ -329,29 +322,24 @@ class _$InProgress implements InProgress {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object>({
|
||||
@required TResult preparing(Preparing value),
|
||||
@required TResult inProgress(InProgress value),
|
||||
@required TResult success(Success value),
|
||||
@required TResult failed(Failed value),
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Preparing value) preparing,
|
||||
required TResult Function(InProgress value) inProgress,
|
||||
required TResult Function(Success value) success,
|
||||
required TResult Function(Failed value) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return inProgress(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object>({
|
||||
TResult preparing(Preparing value),
|
||||
TResult inProgress(InProgress value),
|
||||
TResult success(Success value),
|
||||
TResult failed(Failed value),
|
||||
@required TResult orElse(),
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (inProgress != null) {
|
||||
return inProgress(this);
|
||||
}
|
||||
@@ -365,15 +353,17 @@ class _$InProgress implements InProgress {
|
||||
}
|
||||
|
||||
abstract class InProgress implements UploadState {
|
||||
const factory InProgress({int uploaded, int total}) = _$InProgress;
|
||||
const factory InProgress({required int uploaded, required int total}) =
|
||||
_$InProgress;
|
||||
|
||||
factory InProgress.fromJson(Map<String, dynamic> json) =
|
||||
_$InProgress.fromJson;
|
||||
|
||||
int get uploaded;
|
||||
int get total;
|
||||
int get uploaded => throw _privateConstructorUsedError;
|
||||
int get total => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$InProgressCopyWith<InProgress> get copyWith;
|
||||
$InProgressCopyWith<InProgress> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -416,29 +406,24 @@ class _$Success implements Success {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object>({
|
||||
@required TResult preparing(),
|
||||
@required TResult inProgress(int uploaded, int total),
|
||||
@required TResult success(),
|
||||
@required TResult failed(String error),
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() preparing,
|
||||
required TResult Function(int uploaded, int total) inProgress,
|
||||
required TResult Function() success,
|
||||
required TResult Function(String error) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return success();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object>({
|
||||
TResult preparing(),
|
||||
TResult inProgress(int uploaded, int total),
|
||||
TResult success(),
|
||||
TResult failed(String error),
|
||||
@required TResult orElse(),
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (success != null) {
|
||||
return success();
|
||||
}
|
||||
@@ -447,29 +432,24 @@ class _$Success implements Success {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object>({
|
||||
@required TResult preparing(Preparing value),
|
||||
@required TResult inProgress(InProgress value),
|
||||
@required TResult success(Success value),
|
||||
@required TResult failed(Failed value),
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Preparing value) preparing,
|
||||
required TResult Function(InProgress value) inProgress,
|
||||
required TResult Function(Success value) success,
|
||||
required TResult Function(Failed value) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return success(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object>({
|
||||
TResult preparing(Preparing value),
|
||||
TResult inProgress(InProgress value),
|
||||
TResult success(Success value),
|
||||
TResult failed(Failed value),
|
||||
@required TResult orElse(),
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (success != null) {
|
||||
return success(this);
|
||||
}
|
||||
@@ -506,10 +486,13 @@ class _$FailedCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res>
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object error = freezed,
|
||||
Object? error = freezed,
|
||||
}) {
|
||||
return _then(Failed(
|
||||
error: error == freezed ? _value.error : error as String,
|
||||
error: error == freezed
|
||||
? _value.error
|
||||
: error // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -518,7 +501,7 @@ class _$FailedCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res>
|
||||
|
||||
/// @nodoc
|
||||
class _$Failed implements Failed {
|
||||
const _$Failed({@required this.error}) : assert(error != null);
|
||||
const _$Failed({required this.error});
|
||||
|
||||
factory _$Failed.fromJson(Map<String, dynamic> json) =>
|
||||
_$_$FailedFromJson(json);
|
||||
@@ -550,29 +533,24 @@ class _$Failed implements Failed {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object>({
|
||||
@required TResult preparing(),
|
||||
@required TResult inProgress(int uploaded, int total),
|
||||
@required TResult success(),
|
||||
@required TResult failed(String error),
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() preparing,
|
||||
required TResult Function(int uploaded, int total) inProgress,
|
||||
required TResult Function() success,
|
||||
required TResult Function(String error) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return failed(error);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object>({
|
||||
TResult preparing(),
|
||||
TResult inProgress(int uploaded, int total),
|
||||
TResult success(),
|
||||
TResult failed(String error),
|
||||
@required TResult orElse(),
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (failed != null) {
|
||||
return failed(error);
|
||||
}
|
||||
@@ -581,29 +559,24 @@ class _$Failed implements Failed {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object>({
|
||||
@required TResult preparing(Preparing value),
|
||||
@required TResult inProgress(InProgress value),
|
||||
@required TResult success(Success value),
|
||||
@required TResult failed(Failed value),
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Preparing value) preparing,
|
||||
required TResult Function(InProgress value) inProgress,
|
||||
required TResult Function(Success value) success,
|
||||
required TResult Function(Failed value) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return failed(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object>({
|
||||
TResult preparing(Preparing value),
|
||||
TResult inProgress(InProgress value),
|
||||
TResult success(Success value),
|
||||
TResult failed(Failed value),
|
||||
@required TResult orElse(),
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (failed != null) {
|
||||
return failed(this);
|
||||
}
|
||||
@@ -617,11 +590,11 @@ class _$Failed implements Failed {
|
||||
}
|
||||
|
||||
abstract class Failed implements UploadState {
|
||||
const factory Failed({@required String error}) = _$Failed;
|
||||
const factory Failed({required String error}) = _$Failed;
|
||||
|
||||
factory Failed.fromJson(Map<String, dynamic> json) = _$Failed.fromJson;
|
||||
|
||||
String get error;
|
||||
String get error => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$FailedCopyWith<Failed> get copyWith;
|
||||
$FailedCopyWith<Failed> get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ part of 'attachment_file.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
AttachmentFile _$AttachmentFileFromJson(Map json) {
|
||||
AttachmentFile _$AttachmentFileFromJson(Map<String, dynamic> json) {
|
||||
return AttachmentFile(
|
||||
path: json['path'] as String,
|
||||
name: json['name'] as String,
|
||||
bytes: _fromString(json['bytes'] as String),
|
||||
size: json['size'] as int,
|
||||
path: json['path'] as String?,
|
||||
name: json['name'] as String?,
|
||||
bytes: _fromString(json['bytes'] as String?),
|
||||
size: json['size'] as int?,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,14 +23,14 @@ Map<String, dynamic> _$AttachmentFileToJson(AttachmentFile instance) =>
|
||||
'size': instance.size,
|
||||
};
|
||||
|
||||
_$Preparing _$_$PreparingFromJson(Map json) {
|
||||
_$Preparing _$_$PreparingFromJson(Map<String, dynamic> json) {
|
||||
return _$Preparing();
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$_$PreparingToJson(_$Preparing instance) =>
|
||||
<String, dynamic>{};
|
||||
|
||||
_$InProgress _$_$InProgressFromJson(Map json) {
|
||||
_$InProgress _$_$InProgressFromJson(Map<String, dynamic> json) {
|
||||
return _$InProgress(
|
||||
uploaded: json['uploaded'] as int,
|
||||
total: json['total'] as int,
|
||||
@@ -43,14 +43,14 @@ Map<String, dynamic> _$_$InProgressToJson(_$InProgress instance) =>
|
||||
'total': instance.total,
|
||||
};
|
||||
|
||||
_$Success _$_$SuccessFromJson(Map json) {
|
||||
_$Success _$_$SuccessFromJson(Map<String, dynamic> json) {
|
||||
return _$Success();
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$_$SuccessToJson(_$Success instance) =>
|
||||
<String, dynamic>{};
|
||||
|
||||
_$Failed _$_$FailedFromJson(Map json) {
|
||||
_$Failed _$_$FailedFromJson(Map<String, dynamic> json) {
|
||||
return _$Failed(
|
||||
error: json['error'] as String,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:stream_chat/src/models/command.dart';
|
||||
|
||||
part 'channel_config.g.dart';
|
||||
|
||||
/// The class that contains the information about the configuration of a channel
|
||||
@@ -7,35 +8,38 @@ part 'channel_config.g.dart';
|
||||
class ChannelConfig {
|
||||
/// Constructor used for json serialization
|
||||
ChannelConfig({
|
||||
this.automod,
|
||||
this.commands,
|
||||
this.connectEvents,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.maxMessageLength,
|
||||
this.messageRetention,
|
||||
this.mutes,
|
||||
this.name,
|
||||
this.reactions,
|
||||
this.readEvents,
|
||||
this.replies,
|
||||
this.search,
|
||||
this.typingEvents,
|
||||
this.uploads,
|
||||
this.urlEnrichment,
|
||||
});
|
||||
this.automod = 'flag',
|
||||
this.commands = const [],
|
||||
this.connectEvents = false,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
this.maxMessageLength = 0,
|
||||
this.messageRetention = '',
|
||||
this.mutes = false,
|
||||
this.reactions = false,
|
||||
this.readEvents = false,
|
||||
this.replies = false,
|
||||
this.search = false,
|
||||
this.typingEvents = false,
|
||||
this.uploads = false,
|
||||
this.urlEnrichment = false,
|
||||
}) : createdAt = createdAt ?? DateTime.now(),
|
||||
updatedAt = updatedAt ?? DateTime.now();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory ChannelConfig.fromJson(Map<String, dynamic> json) =>
|
||||
_$ChannelConfigFromJson(json);
|
||||
|
||||
/// Moderation configuration
|
||||
@JsonKey(defaultValue: 'flag')
|
||||
final String automod;
|
||||
|
||||
/// List of available commands
|
||||
@JsonKey(defaultValue: [])
|
||||
final List<Command> commands;
|
||||
|
||||
/// True if the channel should send connect events
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool connectEvents;
|
||||
|
||||
/// Date of channel creation
|
||||
@@ -45,36 +49,43 @@ class ChannelConfig {
|
||||
final DateTime updatedAt;
|
||||
|
||||
/// Max channel message length
|
||||
@JsonKey(defaultValue: 0)
|
||||
final int maxMessageLength;
|
||||
|
||||
/// Duration of message retention
|
||||
@JsonKey(defaultValue: '')
|
||||
final String messageRetention;
|
||||
|
||||
/// True if users can be muted
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool mutes;
|
||||
|
||||
/// Name of the channel
|
||||
final String name;
|
||||
|
||||
/// True if reaction are active for this channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool reactions;
|
||||
|
||||
/// True if readEvents are active for this channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool readEvents;
|
||||
|
||||
/// True if reply message are active for this channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool replies;
|
||||
|
||||
/// True if it's possible to perform a search in this channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool search;
|
||||
|
||||
/// True if typing events should be sent for this channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool typingEvents;
|
||||
|
||||
/// True if it's possible to upload files to this channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool uploads;
|
||||
|
||||
/// True if urls appears as attachments
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool urlEnrichment;
|
||||
|
||||
/// Serialize to json
|
||||
|
||||
@@ -6,48 +6,43 @@ part of 'channel_config.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ChannelConfig _$ChannelConfigFromJson(Map json) {
|
||||
ChannelConfig _$ChannelConfigFromJson(Map<String, dynamic> json) {
|
||||
return ChannelConfig(
|
||||
automod: json['automod'] as String,
|
||||
commands: (json['commands'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Command.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
connectEvents: json['connect_events'] as bool,
|
||||
automod: json['automod'] as String? ?? 'flag',
|
||||
commands: (json['commands'] as List<dynamic>?)
|
||||
?.map((e) => Command.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
connectEvents: json['connect_events'] as bool? ?? false,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: json['updated_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['updated_at'] as String),
|
||||
maxMessageLength: json['max_message_length'] as int,
|
||||
messageRetention: json['message_retention'] as String,
|
||||
mutes: json['mutes'] as bool,
|
||||
name: json['name'] as String,
|
||||
reactions: json['reactions'] as bool,
|
||||
readEvents: json['read_events'] as bool,
|
||||
replies: json['replies'] as bool,
|
||||
search: json['search'] as bool,
|
||||
typingEvents: json['typing_events'] as bool,
|
||||
uploads: json['uploads'] as bool,
|
||||
urlEnrichment: json['url_enrichment'] as bool,
|
||||
maxMessageLength: json['max_message_length'] as int? ?? 0,
|
||||
messageRetention: json['message_retention'] as String? ?? '',
|
||||
mutes: json['mutes'] as bool? ?? false,
|
||||
reactions: json['reactions'] as bool? ?? false,
|
||||
readEvents: json['read_events'] as bool? ?? false,
|
||||
replies: json['replies'] as bool? ?? false,
|
||||
search: json['search'] as bool? ?? false,
|
||||
typingEvents: json['typing_events'] as bool? ?? false,
|
||||
uploads: json['uploads'] as bool? ?? false,
|
||||
urlEnrichment: json['url_enrichment'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$ChannelConfigToJson(ChannelConfig instance) =>
|
||||
<String, dynamic>{
|
||||
'automod': instance.automod,
|
||||
'commands': instance.commands?.map((e) => e?.toJson())?.toList(),
|
||||
'commands': instance.commands.map((e) => e.toJson()).toList(),
|
||||
'connect_events': instance.connectEvents,
|
||||
'created_at': instance.createdAt?.toIso8601String(),
|
||||
'updated_at': instance.updatedAt?.toIso8601String(),
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'max_message_length': instance.maxMessageLength,
|
||||
'message_retention': instance.messageRetention,
|
||||
'mutes': instance.mutes,
|
||||
'name': instance.name,
|
||||
'reactions': instance.reactions,
|
||||
'read_events': instance.readEvents,
|
||||
'replies': instance.replies,
|
||||
|
||||
@@ -10,20 +10,29 @@ part 'channel_model.g.dart';
|
||||
class ChannelModel {
|
||||
/// Constructor used for json serialization
|
||||
ChannelModel({
|
||||
this.id,
|
||||
this.type,
|
||||
this.cid,
|
||||
this.config,
|
||||
String? id,
|
||||
String? type,
|
||||
String? cid,
|
||||
ChannelConfig? config,
|
||||
this.createdBy,
|
||||
this.frozen,
|
||||
this.frozen = false,
|
||||
this.lastMessageAt,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
this.deletedAt,
|
||||
this.memberCount,
|
||||
this.extraData,
|
||||
this.memberCount = 0,
|
||||
this.extraData = const {},
|
||||
this.team,
|
||||
});
|
||||
}) : assert(
|
||||
(cid != null && cid.contains(':')) || (id != null && type != null),
|
||||
'provide either a cid or an id and type',
|
||||
),
|
||||
id = id ?? cid!.split(':')[1],
|
||||
type = type ?? cid!.split(':')[0],
|
||||
cid = cid ?? '$type:$id',
|
||||
config = config ?? ChannelConfig(),
|
||||
createdAt = createdAt ?? DateTime.now(),
|
||||
updatedAt = updatedAt ?? DateTime.now();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory ChannelModel.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -46,15 +55,15 @@ class ChannelModel {
|
||||
|
||||
/// The user that created this channel
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final User createdBy;
|
||||
final User? createdBy;
|
||||
|
||||
/// True if this channel is frozen
|
||||
@JsonKey(includeIfNull: false)
|
||||
@JsonKey(includeIfNull: false, defaultValue: false)
|
||||
final bool frozen;
|
||||
|
||||
/// The date of the last message
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime lastMessageAt;
|
||||
final DateTime? lastMessageAt;
|
||||
|
||||
/// The date of channel creation
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@@ -66,19 +75,23 @@ class ChannelModel {
|
||||
|
||||
/// The date of channel deletion
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime deletedAt;
|
||||
final DateTime? deletedAt;
|
||||
|
||||
/// The count of this channel members
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false, toJson: Serialization.readOnly, defaultValue: 0)
|
||||
final int memberCount;
|
||||
|
||||
/// Map of custom channel extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, dynamic> extraData;
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
defaultValue: {},
|
||||
)
|
||||
final Map<String, Object> 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.
|
||||
@@ -99,29 +112,28 @@ class ChannelModel {
|
||||
|
||||
/// Shortcut for channel name
|
||||
String get name =>
|
||||
extraData?.containsKey('name') == true ? extraData['name'] : cid;
|
||||
extraData.containsKey('name') ? extraData['name'] as String : cid;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$ChannelModelToJson(this),
|
||||
topLevelFields,
|
||||
);
|
||||
|
||||
/// Creates a copy of [ChannelModel] with specified attributes overridden.
|
||||
ChannelModel copyWith({
|
||||
String id,
|
||||
String type,
|
||||
String cid,
|
||||
ChannelConfig config,
|
||||
User createdBy,
|
||||
bool frozen,
|
||||
DateTime lastMessageAt,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
DateTime deletedAt,
|
||||
int memberCount,
|
||||
Map<String, dynamic> extraData,
|
||||
String team,
|
||||
String? id,
|
||||
String? type,
|
||||
String? cid,
|
||||
ChannelConfig? config,
|
||||
User? createdBy,
|
||||
bool? frozen,
|
||||
DateTime? lastMessageAt,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? deletedAt,
|
||||
int? memberCount,
|
||||
Map<String, Object>? extraData,
|
||||
String? team,
|
||||
}) =>
|
||||
ChannelModel(
|
||||
id: id ?? this.id,
|
||||
@@ -141,7 +153,7 @@ class ChannelModel {
|
||||
|
||||
/// Returns a new [ChannelModel] that is a combination of this channelModel
|
||||
/// and the given [other] channelModel.
|
||||
ChannelModel merge(ChannelModel other) {
|
||||
ChannelModel merge(ChannelModel? other) {
|
||||
if (other == null) return this;
|
||||
return copyWith(
|
||||
id: other.id,
|
||||
|
||||
@@ -6,22 +6,18 @@ part of 'channel_model.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ChannelModel _$ChannelModelFromJson(Map json) {
|
||||
ChannelModel _$ChannelModelFromJson(Map<String, dynamic> json) {
|
||||
return ChannelModel(
|
||||
id: json['id'] as String,
|
||||
type: json['type'] as String,
|
||||
cid: json['cid'] as String,
|
||||
id: json['id'] as String?,
|
||||
type: json['type'] as String?,
|
||||
cid: json['cid'] as String?,
|
||||
config: json['config'] == null
|
||||
? null
|
||||
: ChannelConfig.fromJson((json['config'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: ChannelConfig.fromJson(json['config'] as Map<String, dynamic>),
|
||||
createdBy: json['created_by'] == null
|
||||
? null
|
||||
: User.fromJson((json['created_by'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
frozen: json['frozen'] as bool,
|
||||
: User.fromJson(json['created_by'] as Map<String, dynamic>),
|
||||
frozen: json['frozen'] as bool? ?? false,
|
||||
lastMessageAt: json['last_message_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['last_message_at'] as String),
|
||||
@@ -34,11 +30,12 @@ ChannelModel _$ChannelModelFromJson(Map json) {
|
||||
deletedAt: json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
memberCount: json['member_count'] as int,
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
),
|
||||
team: json['team'] as String,
|
||||
memberCount: json['member_count'] as int? ?? 0,
|
||||
extraData: (json['extra_data'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, e as Object),
|
||||
) ??
|
||||
{},
|
||||
team: json['team'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -57,13 +54,13 @@ Map<String, dynamic> _$ChannelModelToJson(ChannelModel instance) {
|
||||
writeNotNull('cid', readonly(instance.cid));
|
||||
writeNotNull('config', readonly(instance.config));
|
||||
writeNotNull('created_by', readonly(instance.createdBy));
|
||||
writeNotNull('frozen', instance.frozen);
|
||||
val['frozen'] = instance.frozen;
|
||||
writeNotNull('last_message_at', readonly(instance.lastMessageAt));
|
||||
writeNotNull('created_at', readonly(instance.createdAt));
|
||||
writeNotNull('updated_at', readonly(instance.updatedAt));
|
||||
writeNotNull('deleted_at', readonly(instance.deletedAt));
|
||||
writeNotNull('member_count', readonly(instance.memberCount));
|
||||
writeNotNull('extra_data', instance.extraData);
|
||||
val['extra_data'] = instance.extraData;
|
||||
writeNotNull('team', readonly(instance.team));
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -22,24 +22,29 @@ class ChannelState {
|
||||
});
|
||||
|
||||
/// The channel to which this state belongs
|
||||
final ChannelModel channel;
|
||||
final ChannelModel? channel;
|
||||
|
||||
/// A paginated list of channel messages
|
||||
@JsonKey(defaultValue: <Message>[])
|
||||
final List<Message> messages;
|
||||
|
||||
/// A paginated list of channel members
|
||||
@JsonKey(defaultValue: <Member>[])
|
||||
final List<Member> members;
|
||||
|
||||
/// A paginated list of pinned messages
|
||||
@JsonKey(defaultValue: <Message>[])
|
||||
final List<Message> pinnedMessages;
|
||||
|
||||
/// The count of users watching the channel
|
||||
final int watcherCount;
|
||||
final int? watcherCount;
|
||||
|
||||
/// A paginated list of users watching the channel
|
||||
@JsonKey(defaultValue: <User>[])
|
||||
final List<User> watchers;
|
||||
|
||||
/// The list of channel reads
|
||||
@JsonKey(defaultValue: <Read>[])
|
||||
final List<Read> read;
|
||||
|
||||
/// Create a new instance from a json
|
||||
@@ -51,13 +56,13 @@ class ChannelState {
|
||||
|
||||
/// Creates a copy of [ChannelState] with specified attributes overridden.
|
||||
ChannelState copyWith({
|
||||
ChannelModel channel,
|
||||
List<Message> messages,
|
||||
List<Member> members,
|
||||
List<Message> pinnedMessages,
|
||||
int watcherCount,
|
||||
List<User> watchers,
|
||||
List<Read> read,
|
||||
ChannelModel? channel,
|
||||
List<Message>? messages,
|
||||
List<Member>? members,
|
||||
List<Message>? pinnedMessages,
|
||||
int? watcherCount,
|
||||
List<User>? watchers,
|
||||
List<Read>? read,
|
||||
}) =>
|
||||
ChannelState(
|
||||
channel: channel ?? this.channel,
|
||||
|
||||
@@ -6,60 +6,43 @@ part of 'channel_state.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ChannelState _$ChannelStateFromJson(Map json) {
|
||||
ChannelState _$ChannelStateFromJson(Map<String, dynamic> json) {
|
||||
return ChannelState(
|
||||
channel: json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
messages: (json['messages'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Message.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
members: (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
pinnedMessages: (json['pinned_messages'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Message.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
watcherCount: json['watcher_count'] as int,
|
||||
watchers: (json['watchers'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: User.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
read: (json['read'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Read.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
: ChannelModel.fromJson(json['channel'] as Map<String, dynamic>),
|
||||
messages: (json['messages'] as List<dynamic>?)
|
||||
?.map((e) => Message.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
members: (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
pinnedMessages: (json['pinned_messages'] as List<dynamic>?)
|
||||
?.map((e) => Message.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
watcherCount: json['watcher_count'] as int?,
|
||||
watchers: (json['watchers'] as List<dynamic>?)
|
||||
?.map((e) => User.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
read: (json['read'] as List<dynamic>?)
|
||||
?.map((e) => Read.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$ChannelStateToJson(ChannelState instance) =>
|
||||
<String, dynamic>{
|
||||
'channel': instance.channel?.toJson(),
|
||||
'messages': instance.messages?.map((e) => e?.toJson())?.toList(),
|
||||
'members': instance.members?.map((e) => e?.toJson())?.toList(),
|
||||
'messages': instance.messages.map((e) => e.toJson()).toList(),
|
||||
'members': instance.members.map((e) => e.toJson()).toList(),
|
||||
'pinned_messages':
|
||||
instance.pinnedMessages?.map((e) => e?.toJson())?.toList(),
|
||||
instance.pinnedMessages.map((e) => e.toJson()).toList(),
|
||||
'watcher_count': instance.watcherCount,
|
||||
'watchers': instance.watchers?.map((e) => e?.toJson())?.toList(),
|
||||
'read': instance.read?.map((e) => e?.toJson())?.toList(),
|
||||
'watchers': instance.watchers.map((e) => e.toJson()).toList(),
|
||||
'read': instance.read.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
|
||||
@@ -7,9 +7,9 @@ part 'command.g.dart';
|
||||
class Command {
|
||||
/// Constructor used for json serialization
|
||||
Command({
|
||||
this.name,
|
||||
this.description,
|
||||
this.args,
|
||||
required this.name,
|
||||
required this.description,
|
||||
required this.args,
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'command.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Command _$CommandFromJson(Map json) {
|
||||
Command _$CommandFromJson(Map<String, dynamic> json) {
|
||||
return Command(
|
||||
name: json['name'] as String,
|
||||
description: json['description'] as String,
|
||||
|
||||
@@ -7,8 +7,8 @@ part 'device.g.dart';
|
||||
class Device {
|
||||
/// Constructor used for json serialization
|
||||
Device({
|
||||
this.id,
|
||||
this.pushProvider,
|
||||
required this.id,
|
||||
required this.pushProvider,
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'device.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Device _$DeviceFromJson(Map json) {
|
||||
Device _$DeviceFromJson(Map<String, dynamic> json) {
|
||||
return Device(
|
||||
id: json['id'] as String,
|
||||
pushProvider: json['push_provider'] as String,
|
||||
|
||||
@@ -10,7 +10,7 @@ part 'event.g.dart';
|
||||
@JsonSerializable()
|
||||
class Event {
|
||||
/// Constructor used for json serialization
|
||||
Event({
|
||||
const Event({
|
||||
this.type,
|
||||
this.cid,
|
||||
this.connectionId,
|
||||
@@ -27,72 +27,73 @@ class Event {
|
||||
this.channelId,
|
||||
this.channelType,
|
||||
this.parentId,
|
||||
this.extraData,
|
||||
}) : isLocal = true;
|
||||
this.extraData = const {},
|
||||
this.isLocal = true,
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Event.fromJson(Map<String, dynamic> json) =>
|
||||
_$EventFromJson(Serialization.moveToExtraDataFromRoot(
|
||||
json,
|
||||
topLevelFields,
|
||||
))
|
||||
..isLocal = false;
|
||||
));
|
||||
|
||||
/// The type of the event
|
||||
/// [EventType] contains some predefined constant types
|
||||
final String type;
|
||||
final String? type;
|
||||
|
||||
/// The channel cid to which the event belongs
|
||||
final String cid;
|
||||
final String? cid;
|
||||
|
||||
/// The channel id to which the event belongs
|
||||
final String channelId;
|
||||
final String? channelId;
|
||||
|
||||
/// The channel type to which the event belongs
|
||||
final String channelType;
|
||||
final String? channelType;
|
||||
|
||||
/// The connection id in which the event has been sent
|
||||
final String connectionId;
|
||||
final String? connectionId;
|
||||
|
||||
/// The date of creation of the event
|
||||
final DateTime createdAt;
|
||||
final DateTime? createdAt;
|
||||
|
||||
/// User object of the health check user
|
||||
final OwnUser me;
|
||||
final OwnUser? me;
|
||||
|
||||
/// User object of the current user
|
||||
final User user;
|
||||
final User? user;
|
||||
|
||||
/// The message sent with the event
|
||||
final Message message;
|
||||
final Message? message;
|
||||
|
||||
/// The channel sent with the event
|
||||
final EventChannel channel;
|
||||
final EventChannel? channel;
|
||||
|
||||
/// The member sent with the event
|
||||
final Member member;
|
||||
final Member? member;
|
||||
|
||||
/// The reaction sent with the event
|
||||
final Reaction reaction;
|
||||
final Reaction? reaction;
|
||||
|
||||
/// The number of unread messages for current user
|
||||
final int totalUnreadCount;
|
||||
final int? totalUnreadCount;
|
||||
|
||||
/// User total unread channels
|
||||
final int unreadChannels;
|
||||
final int? unreadChannels;
|
||||
|
||||
/// Online status
|
||||
final bool online;
|
||||
final bool? online;
|
||||
|
||||
/// The id of the parent message of a thread
|
||||
final String parentId;
|
||||
final String? parentId;
|
||||
|
||||
/// True if the event is generated by this client
|
||||
bool isLocal;
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool isLocal;
|
||||
|
||||
/// Map of custom channel extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, dynamic> extraData;
|
||||
@JsonKey(defaultValue: {})
|
||||
final Map<String, Object> extraData;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
@@ -119,28 +120,27 @@ class Event {
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$EventToJson(this),
|
||||
topLevelFields,
|
||||
);
|
||||
|
||||
/// Creates a copy of [Event] with specified attributes overridden.
|
||||
Event copyWith({
|
||||
String type,
|
||||
String cid,
|
||||
String channelId,
|
||||
String channelType,
|
||||
String connectionId,
|
||||
DateTime createdAt,
|
||||
OwnUser me,
|
||||
User user,
|
||||
Message message,
|
||||
EventChannel channel,
|
||||
Member member,
|
||||
Reaction reaction,
|
||||
int totalUnreadCount,
|
||||
int unreadChannels,
|
||||
bool online,
|
||||
String parentId,
|
||||
Map<String, dynamic> extraData,
|
||||
String? type,
|
||||
String? cid,
|
||||
String? channelId,
|
||||
String? channelType,
|
||||
String? connectionId,
|
||||
DateTime? createdAt,
|
||||
OwnUser? me,
|
||||
User? user,
|
||||
Message? message,
|
||||
EventChannel? channel,
|
||||
Member? member,
|
||||
Reaction? reaction,
|
||||
int? totalUnreadCount,
|
||||
int? unreadChannels,
|
||||
bool? online,
|
||||
String? parentId,
|
||||
Map<String, Object>? extraData,
|
||||
}) =>
|
||||
Event(
|
||||
type: type ?? this.type,
|
||||
@@ -169,18 +169,18 @@ class EventChannel extends ChannelModel {
|
||||
/// Constructor used for json serialization
|
||||
EventChannel({
|
||||
this.members,
|
||||
String id,
|
||||
String type,
|
||||
String cid,
|
||||
ChannelConfig config,
|
||||
User createdBy,
|
||||
bool frozen,
|
||||
DateTime lastMessageAt,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
DateTime deletedAt,
|
||||
int memberCount,
|
||||
Map<String, dynamic> extraData,
|
||||
String? id,
|
||||
String? type,
|
||||
required String cid,
|
||||
required ChannelConfig config,
|
||||
User? createdBy,
|
||||
bool frozen = false,
|
||||
DateTime? lastMessageAt,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
DateTime? deletedAt,
|
||||
required int memberCount,
|
||||
Map<String, Object>? extraData,
|
||||
}) : super(
|
||||
id: id,
|
||||
type: type,
|
||||
@@ -193,7 +193,7 @@ class EventChannel extends ChannelModel {
|
||||
updatedAt: updatedAt,
|
||||
deletedAt: deletedAt,
|
||||
memberCount: memberCount,
|
||||
extraData: extraData,
|
||||
extraData: extraData ?? {},
|
||||
);
|
||||
|
||||
/// Create a new instance from a json
|
||||
@@ -204,7 +204,7 @@ class EventChannel extends ChannelModel {
|
||||
));
|
||||
|
||||
/// A paginated list of channel members
|
||||
final List<Member> members;
|
||||
final List<Member>? members;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
@@ -217,6 +217,5 @@ class EventChannel extends ChannelModel {
|
||||
@override
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$EventChannelToJson(this),
|
||||
topLevelFields,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,126 +6,93 @@ part of 'event.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Event _$EventFromJson(Map json) {
|
||||
Event _$EventFromJson(Map<String, dynamic> json) {
|
||||
return Event(
|
||||
type: json['type'] as String,
|
||||
cid: json['cid'] as String,
|
||||
connectionId: json['connection_id'] as String,
|
||||
type: json['type'] as String?,
|
||||
cid: json['cid'] as String?,
|
||||
connectionId: json['connection_id'] as String?,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
me: json['me'] == null
|
||||
? null
|
||||
: OwnUser.fromJson((json['me'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: OwnUser.fromJson(json['me'] as Map<String, dynamic>),
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: User.fromJson(json['user'] as Map<String, dynamic>),
|
||||
message: json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
totalUnreadCount: json['total_unread_count'] as int,
|
||||
unreadChannels: json['unread_channels'] as int,
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>),
|
||||
totalUnreadCount: json['total_unread_count'] as int?,
|
||||
unreadChannels: json['unread_channels'] as int?,
|
||||
reaction: json['reaction'] == null
|
||||
? null
|
||||
: Reaction.fromJson((json['reaction'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
online: json['online'] as bool,
|
||||
: Reaction.fromJson(json['reaction'] as Map<String, dynamic>),
|
||||
online: json['online'] as bool?,
|
||||
channel: json['channel'] == null
|
||||
? null
|
||||
: EventChannel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: EventChannel.fromJson(json['channel'] as Map<String, dynamic>),
|
||||
member: json['member'] == null
|
||||
? null
|
||||
: Member.fromJson((json['member'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
channelId: json['channel_id'] as String,
|
||||
channelType: json['channel_type'] as String,
|
||||
parentId: json['parent_id'] as String,
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
),
|
||||
)..isLocal = json['is_local'] as bool;
|
||||
: Member.fromJson(json['member'] as Map<String, dynamic>),
|
||||
channelId: json['channel_id'] as String?,
|
||||
channelType: json['channel_type'] as String?,
|
||||
parentId: json['parent_id'] as String?,
|
||||
extraData: (json['extra_data'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, e as Object),
|
||||
) ??
|
||||
{},
|
||||
isLocal: json['is_local'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$EventToJson(Event instance) {
|
||||
final val = <String, dynamic>{
|
||||
'type': instance.type,
|
||||
'cid': instance.cid,
|
||||
'channel_id': instance.channelId,
|
||||
'channel_type': instance.channelType,
|
||||
'connection_id': instance.connectionId,
|
||||
'created_at': instance.createdAt?.toIso8601String(),
|
||||
'me': instance.me?.toJson(),
|
||||
'user': instance.user?.toJson(),
|
||||
'message': instance.message?.toJson(),
|
||||
'channel': instance.channel?.toJson(),
|
||||
'member': instance.member?.toJson(),
|
||||
'reaction': instance.reaction?.toJson(),
|
||||
'total_unread_count': instance.totalUnreadCount,
|
||||
'unread_channels': instance.unreadChannels,
|
||||
'online': instance.online,
|
||||
'parent_id': instance.parentId,
|
||||
'is_local': instance.isLocal,
|
||||
};
|
||||
Map<String, dynamic> _$EventToJson(Event instance) => <String, dynamic>{
|
||||
'type': instance.type,
|
||||
'cid': instance.cid,
|
||||
'channel_id': instance.channelId,
|
||||
'channel_type': instance.channelType,
|
||||
'connection_id': instance.connectionId,
|
||||
'created_at': instance.createdAt?.toIso8601String(),
|
||||
'me': instance.me?.toJson(),
|
||||
'user': instance.user?.toJson(),
|
||||
'message': instance.message?.toJson(),
|
||||
'channel': instance.channel?.toJson(),
|
||||
'member': instance.member?.toJson(),
|
||||
'reaction': instance.reaction?.toJson(),
|
||||
'total_unread_count': instance.totalUnreadCount,
|
||||
'unread_channels': instance.unreadChannels,
|
||||
'online': instance.online,
|
||||
'parent_id': instance.parentId,
|
||||
'is_local': instance.isLocal,
|
||||
'extra_data': instance.extraData,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('extra_data', instance.extraData);
|
||||
return val;
|
||||
}
|
||||
|
||||
EventChannel _$EventChannelFromJson(Map json) {
|
||||
EventChannel _$EventChannelFromJson(Map<String, dynamic> json) {
|
||||
return EventChannel(
|
||||
members: (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
id: json['id'] as String,
|
||||
type: json['type'] as String,
|
||||
members: (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
id: json['id'] as String?,
|
||||
type: json['type'] as String?,
|
||||
cid: json['cid'] as String,
|
||||
config: json['config'] == null
|
||||
? null
|
||||
: ChannelConfig.fromJson((json['config'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
config: ChannelConfig.fromJson(json['config'] as Map<String, dynamic>),
|
||||
createdBy: json['created_by'] == null
|
||||
? null
|
||||
: User.fromJson((json['created_by'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
frozen: json['frozen'] as bool,
|
||||
: User.fromJson(json['created_by'] as Map<String, dynamic>),
|
||||
frozen: json['frozen'] as bool? ?? false,
|
||||
lastMessageAt: json['last_message_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['last_message_at'] as String),
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: json['updated_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['updated_at'] as String),
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt: json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
memberCount: json['member_count'] as int,
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
),
|
||||
memberCount: json['member_count'] as int? ?? 0,
|
||||
extraData: (json['extra_data'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, e as Object),
|
||||
) ??
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -144,13 +111,13 @@ Map<String, dynamic> _$EventChannelToJson(EventChannel instance) {
|
||||
writeNotNull('cid', readonly(instance.cid));
|
||||
writeNotNull('config', readonly(instance.config));
|
||||
writeNotNull('created_by', readonly(instance.createdBy));
|
||||
writeNotNull('frozen', instance.frozen);
|
||||
val['frozen'] = instance.frozen;
|
||||
writeNotNull('last_message_at', readonly(instance.lastMessageAt));
|
||||
writeNotNull('created_at', readonly(instance.createdAt));
|
||||
writeNotNull('updated_at', readonly(instance.updatedAt));
|
||||
writeNotNull('deleted_at', readonly(instance.deletedAt));
|
||||
writeNotNull('member_count', readonly(instance.memberCount));
|
||||
writeNotNull('extra_data', instance.extraData);
|
||||
val['members'] = instance.members?.map((e) => e?.toJson())?.toList();
|
||||
val['extra_data'] = instance.extraData;
|
||||
val['members'] = instance.members?.map((e) => e.toJson()).toList();
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
// ignore_for_file: non_constant_identifier_names, constant_identifier_names
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
const _groupOperators = [
|
||||
FilterOperator.and,
|
||||
FilterOperator.or,
|
||||
FilterOperator.nor,
|
||||
];
|
||||
|
||||
/// Possible operators to use in filters.
|
||||
enum FilterOperator {
|
||||
/// Matches values that are equal to a specified value.
|
||||
equal,
|
||||
|
||||
/// Matches all values that are not equal to a specified value.
|
||||
notEqual,
|
||||
|
||||
/// Matches values that are greater than a specified value.
|
||||
greater,
|
||||
|
||||
/// Matches values that are greater than a specified value.
|
||||
greaterOrEqual,
|
||||
|
||||
/// Matches values that are less than a specified value.
|
||||
less,
|
||||
|
||||
/// Matches values that are less than or equal to a specified value.
|
||||
lessOrEqual,
|
||||
|
||||
/// Matches any of the values specified in an array.
|
||||
in_,
|
||||
|
||||
/// Matches none of the values specified in an array.
|
||||
notIn,
|
||||
|
||||
/// Matches values by performing text search with the specified value.
|
||||
query,
|
||||
|
||||
/// Matches values with the specified prefix.
|
||||
autoComplete,
|
||||
|
||||
/// Matches values that exist/don't exist based on the specified boolean value.
|
||||
exists,
|
||||
|
||||
/// Matches all the values specified in an array.
|
||||
and,
|
||||
|
||||
/// Matches at least one of the values specified in an array.
|
||||
or,
|
||||
|
||||
/// Matches none of the values specified in an array.
|
||||
nor,
|
||||
}
|
||||
|
||||
/// Helper extension for [FilterOperator]
|
||||
extension FilterOperatorX on FilterOperator {
|
||||
/// Converts [FilterOperator] into rew values
|
||||
String get rawValue => {
|
||||
FilterOperator.equal: '\$eq',
|
||||
FilterOperator.notEqual: '\$ne',
|
||||
FilterOperator.greater: '\$gt',
|
||||
FilterOperator.greaterOrEqual: '\$gte',
|
||||
FilterOperator.less: '\$lt',
|
||||
FilterOperator.lessOrEqual: '\$lte',
|
||||
FilterOperator.in_: '\$in',
|
||||
FilterOperator.notIn: '\$nin',
|
||||
FilterOperator.query: '\$q',
|
||||
FilterOperator.autoComplete: '\$autocomplete',
|
||||
FilterOperator.exists: '\$exists',
|
||||
FilterOperator.and: '\$and',
|
||||
FilterOperator.or: '\$or',
|
||||
FilterOperator.nor: '\$nor',
|
||||
}[this]!;
|
||||
}
|
||||
|
||||
/// Stream supports a limited set of filters for querying channels,
|
||||
/// users and members. The example below shows how to filter for channels
|
||||
/// of type messaging where the current user is a member
|
||||
///
|
||||
/// ```dart
|
||||
/// final filter = Filter.and(
|
||||
/// Filter.equal('type', 'messaging'),
|
||||
/// Filter.in_('members', [user.id])
|
||||
/// )
|
||||
/// ```
|
||||
/// See <a href="https://getstream.io/chat/docs/query_channels/?language=dart" target="_top">Query Channels Documentation</a>
|
||||
class Filter extends Equatable {
|
||||
const Filter.__({
|
||||
required this.operator,
|
||||
required this.value,
|
||||
this.key,
|
||||
});
|
||||
|
||||
Filter._({
|
||||
required FilterOperator operator,
|
||||
required this.value,
|
||||
this.key,
|
||||
}) : operator = operator.rawValue;
|
||||
|
||||
/// Combines the provided filters and matches the values
|
||||
/// matched by all filters.
|
||||
factory Filter.and(List<Filter> filters) =>
|
||||
Filter._(operator: FilterOperator.and, value: filters);
|
||||
|
||||
/// Combines the provided filters and matches the values
|
||||
/// matched by at least one of the filters.
|
||||
factory Filter.or(List<Filter> filters) =>
|
||||
Filter._(operator: FilterOperator.or, value: filters);
|
||||
|
||||
/// Combines the provided filters and matches the values
|
||||
/// not matched by all the filters.
|
||||
factory Filter.nor(List<Filter> filters) =>
|
||||
Filter._(operator: FilterOperator.nor, value: filters);
|
||||
|
||||
/// Matches values that are equal to a specified value.
|
||||
factory Filter.equal(String key, Object value) =>
|
||||
Filter._(operator: FilterOperator.equal, key: key, value: value);
|
||||
|
||||
/// Matches all values that are not equal to a specified value.
|
||||
factory Filter.notEqual(String key, Object value) =>
|
||||
Filter._(operator: FilterOperator.notEqual, key: key, value: value);
|
||||
|
||||
/// Matches values that are greater than a specified value.
|
||||
factory Filter.greater(String key, Object value) =>
|
||||
Filter._(operator: FilterOperator.greater, key: key, value: value);
|
||||
|
||||
/// Matches values that are greater than a specified value.
|
||||
factory Filter.greaterOrEqual(String key, Object value) =>
|
||||
Filter._(operator: FilterOperator.greaterOrEqual, key: key, value: value);
|
||||
|
||||
/// Matches values that are less than a specified value.
|
||||
factory Filter.less(String key, Object value) =>
|
||||
Filter._(operator: FilterOperator.less, key: key, value: value);
|
||||
|
||||
/// Matches values that are less than or equal to a specified value.
|
||||
factory Filter.lessOrEqual(String key, Object value) =>
|
||||
Filter._(operator: FilterOperator.lessOrEqual, key: key, value: value);
|
||||
|
||||
/// Matches any of the values specified in an array.
|
||||
factory Filter.in_(String key, List<Object> values) =>
|
||||
Filter._(operator: FilterOperator.in_, key: key, value: values);
|
||||
|
||||
/// Matches none of the values specified in an array.
|
||||
factory Filter.notIn(String key, List<Object> values) =>
|
||||
Filter._(operator: FilterOperator.notIn, key: key, value: values);
|
||||
|
||||
/// Matches values by performing text search with the specified value.
|
||||
factory Filter.query(String key, String text) =>
|
||||
Filter._(operator: FilterOperator.query, key: key, value: text);
|
||||
|
||||
/// Matches values with the specified prefix.
|
||||
factory Filter.autoComplete(String key, String text) =>
|
||||
Filter._(operator: FilterOperator.autoComplete, key: key, value: text);
|
||||
|
||||
/// Matches values that exist/don't exist based on the specified boolean value.
|
||||
factory Filter.exists(String key, {bool exists = true}) =>
|
||||
Filter._(operator: FilterOperator.exists, key: key, value: exists);
|
||||
|
||||
/// Creates a custom [Filter] if there isn't one already available.
|
||||
const factory Filter.custom({
|
||||
required String operator,
|
||||
required Object value,
|
||||
String? key,
|
||||
}) = Filter.__;
|
||||
|
||||
/// An operator used for the filter. The operator string must start with `$`
|
||||
final String operator;
|
||||
|
||||
/// The "left-hand" side of the filter.
|
||||
/// Specifies the name of the field the filter should match.
|
||||
///
|
||||
/// Some operators like `and` or `or`,
|
||||
/// don't require the key value to be present.
|
||||
/// see-more : [_groupOperators]
|
||||
final String? key;
|
||||
|
||||
/// The "right-hand" side of the filter.
|
||||
/// Specifies the [value] the filter should match.
|
||||
final Object /*List<Object>|List<Filter>|String*/ value;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [operator, key, value];
|
||||
|
||||
/// Serializes to json object
|
||||
Map<String, Object> toJson() {
|
||||
final json = <String, Object>{};
|
||||
final groupOperators = _groupOperators.map((it) => it.rawValue);
|
||||
|
||||
assert(
|
||||
groupOperators.contains(operator) || key != null,
|
||||
'Filter must contain the `key` when the operator is not a '
|
||||
'group operator.',
|
||||
);
|
||||
|
||||
if (groupOperators.contains(operator)) {
|
||||
// Filters with group operators are encoded in the following form:
|
||||
// { $<operator>: [ <filter 1>, <filter 2> ] }
|
||||
json[operator] = value;
|
||||
} else {
|
||||
// Normal filters are encoded in the following form:
|
||||
// { key: { $<operator>: <value> } }
|
||||
json[key!] = {operator: value};
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -12,15 +12,16 @@ class Member {
|
||||
this.user,
|
||||
this.inviteAcceptedAt,
|
||||
this.inviteRejectedAt,
|
||||
this.invited,
|
||||
this.invited = false,
|
||||
this.role,
|
||||
this.userId,
|
||||
this.isModerator,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.banned,
|
||||
this.shadowBanned,
|
||||
});
|
||||
this.isModerator = false,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
this.banned = false,
|
||||
this.shadowBanned = false,
|
||||
}) : createdAt = createdAt ?? DateTime.now(),
|
||||
updatedAt = updatedAt ?? DateTime.now();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Member.fromJson(Map<String, dynamic> json) {
|
||||
@@ -31,30 +32,34 @@ class Member {
|
||||
}
|
||||
|
||||
/// The interested user
|
||||
final User user;
|
||||
final User? user;
|
||||
|
||||
/// The date in which the user accepted the invite to the channel
|
||||
final DateTime inviteAcceptedAt;
|
||||
final DateTime? inviteAcceptedAt;
|
||||
|
||||
/// The date in which the user rejected the invite to the channel
|
||||
final DateTime inviteRejectedAt;
|
||||
final DateTime? inviteRejectedAt;
|
||||
|
||||
/// True if the user has been invited to the channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool invited;
|
||||
|
||||
/// The role of the user in the channel
|
||||
final String role;
|
||||
final String? role;
|
||||
|
||||
/// The id of the interested user
|
||||
final String userId;
|
||||
final String? userId;
|
||||
|
||||
/// True if the user is a moderator of the channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool isModerator;
|
||||
|
||||
/// True if the member is banned from the channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool banned;
|
||||
|
||||
/// True if the member is shadow banned from the channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool shadowBanned;
|
||||
|
||||
/// The date of creation
|
||||
@@ -65,17 +70,17 @@ class Member {
|
||||
|
||||
/// Creates a copy of [Member] with specified attributes overridden.
|
||||
Member copyWith({
|
||||
User user,
|
||||
DateTime inviteAcceptedAt,
|
||||
DateTime inviteRejectedAt,
|
||||
bool invited,
|
||||
String role,
|
||||
String userId,
|
||||
bool isModerator,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
bool banned,
|
||||
bool shadowBanned,
|
||||
User? user,
|
||||
DateTime? inviteAcceptedAt,
|
||||
DateTime? inviteRejectedAt,
|
||||
bool? invited,
|
||||
String? role,
|
||||
String? userId,
|
||||
bool? isModerator,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
bool? banned,
|
||||
bool? shadowBanned,
|
||||
}) =>
|
||||
Member(
|
||||
user: user ?? this.user,
|
||||
|
||||
@@ -6,31 +6,29 @@ part of 'member.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Member _$MemberFromJson(Map json) {
|
||||
Member _$MemberFromJson(Map<String, dynamic> json) {
|
||||
return Member(
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: User.fromJson(json['user'] as Map<String, dynamic>),
|
||||
inviteAcceptedAt: json['invite_accepted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['invite_accepted_at'] as String),
|
||||
inviteRejectedAt: json['invite_rejected_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['invite_rejected_at'] as String),
|
||||
invited: json['invited'] as bool,
|
||||
role: json['role'] as String,
|
||||
userId: json['user_id'] as String,
|
||||
isModerator: json['is_moderator'] as bool,
|
||||
invited: json['invited'] as bool? ?? false,
|
||||
role: json['role'] as String?,
|
||||
userId: json['user_id'] as String?,
|
||||
isModerator: json['is_moderator'] as bool? ?? false,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: json['updated_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['updated_at'] as String),
|
||||
banned: json['banned'] as bool,
|
||||
shadowBanned: json['shadow_banned'] as bool,
|
||||
banned: json['banned'] as bool? ?? false,
|
||||
shadowBanned: json['shadow_banned'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -44,6 +42,6 @@ Map<String, dynamic> _$MemberToJson(Member instance) => <String, dynamic>{
|
||||
'is_moderator': instance.isModerator,
|
||||
'banned': instance.banned,
|
||||
'shadow_banned': instance.shadowBanned,
|
||||
'created_at': instance.createdAt?.toIso8601String(),
|
||||
'updated_at': instance.updatedAt?.toIso8601String(),
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
};
|
||||
|
||||
@@ -45,13 +45,13 @@ enum MessageSendingStatus {
|
||||
class Message extends Equatable {
|
||||
/// Constructor used for json serialization
|
||||
Message({
|
||||
String id,
|
||||
String? id,
|
||||
this.text,
|
||||
this.type,
|
||||
this.attachments,
|
||||
this.mentionedUsers,
|
||||
this.silent,
|
||||
this.shadowed,
|
||||
this.type = 'regular',
|
||||
this.attachments = const [],
|
||||
this.mentionedUsers = const [],
|
||||
this.silent = false,
|
||||
this.shadowed = false,
|
||||
this.reactionCounts,
|
||||
this.reactionScores,
|
||||
this.latestReactions,
|
||||
@@ -63,19 +63,21 @@ class Message extends Equatable {
|
||||
this.threadParticipants,
|
||||
this.showInChannel,
|
||||
this.command,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
this.user,
|
||||
this.pinned = false,
|
||||
this.pinnedAt,
|
||||
DateTime pinExpires,
|
||||
DateTime? pinExpires,
|
||||
this.pinnedBy,
|
||||
this.extraData,
|
||||
this.extraData = const {},
|
||||
this.deletedAt,
|
||||
this.status = MessageSendingStatus.sent,
|
||||
this.skipPush,
|
||||
}) : id = id ?? Uuid().v4(),
|
||||
pinExpires = pinExpires?.toUtc();
|
||||
this.skipPush = false,
|
||||
}) : id = id ?? const Uuid().v4(),
|
||||
pinExpires = pinExpires?.toUtc(),
|
||||
createdAt = createdAt ?? DateTime.now(),
|
||||
updatedAt = updatedAt ?? DateTime.now();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Message.fromJson(Map<String, dynamic> json) => _$MessageFromJson(
|
||||
@@ -86,75 +88,91 @@ class Message extends Equatable {
|
||||
final String id;
|
||||
|
||||
/// The text of this message
|
||||
final String text;
|
||||
final String? text;
|
||||
|
||||
/// The status of a sending message
|
||||
@JsonKey(ignore: true)
|
||||
final MessageSendingStatus status;
|
||||
|
||||
/// The message type
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serialization.readOnly,
|
||||
defaultValue: 'regular',
|
||||
)
|
||||
final String type;
|
||||
|
||||
/// The list of attachments, either provided by the user or generated from a
|
||||
/// command or as a result of URL scraping.
|
||||
@JsonKey(includeIfNull: false)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
defaultValue: [],
|
||||
)
|
||||
final List<Attachment> attachments;
|
||||
|
||||
/// The list of user mentioned in the message
|
||||
@JsonKey(toJson: Serialization.userIds)
|
||||
@JsonKey(
|
||||
toJson: Serialization.userIds,
|
||||
defaultValue: [],
|
||||
)
|
||||
final List<User> mentionedUsers;
|
||||
|
||||
/// A map describing the count of number of every reaction
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final Map<String, int> reactionCounts;
|
||||
final Map<String, int>? reactionCounts;
|
||||
|
||||
/// A map describing the count of score of every reaction
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final Map<String, int> reactionScores;
|
||||
final Map<String, int>? reactionScores;
|
||||
|
||||
/// The latest reactions to the message created by any user.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final List<Reaction> latestReactions;
|
||||
final List<Reaction>? latestReactions;
|
||||
|
||||
/// The reactions added to the message by the current user.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final List<Reaction> ownReactions;
|
||||
final List<Reaction>? ownReactions;
|
||||
|
||||
/// The ID of the parent message, if the message is a thread reply.
|
||||
final String parentId;
|
||||
final String? parentId;
|
||||
|
||||
/// A quoted reply message
|
||||
@JsonKey(toJson: Serialization.readOnly)
|
||||
final Message quotedMessage;
|
||||
final Message? quotedMessage;
|
||||
|
||||
/// The ID of the quoted message, if the message is a quoted reply.
|
||||
final String quotedMessageId;
|
||||
final String? quotedMessageId;
|
||||
|
||||
/// Reserved field indicating the number of replies for this message.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final int replyCount;
|
||||
final int? replyCount;
|
||||
|
||||
/// Reserved field indicating the thread participants for this message.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final List<User> threadParticipants;
|
||||
final List<User>? threadParticipants;
|
||||
|
||||
/// Check if this message needs to show in the channel.
|
||||
final bool showInChannel;
|
||||
final bool? showInChannel;
|
||||
|
||||
/// If true the message is silent
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool silent;
|
||||
|
||||
/// If true the message will not send a push notification
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool skipPush;
|
||||
|
||||
/// If true the message is shadowed
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serialization.readOnly,
|
||||
defaultValue: false,
|
||||
)
|
||||
final bool shadowed;
|
||||
|
||||
/// A used command name.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final String command;
|
||||
final String? command;
|
||||
|
||||
/// Reserved field indicating when the message was created.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@@ -166,27 +184,31 @@ class Message extends Equatable {
|
||||
|
||||
/// User who sent the message
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final User user;
|
||||
final User? user;
|
||||
|
||||
/// If true the message is pinned
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool pinned;
|
||||
|
||||
/// Reserved field indicating when the message was pinned
|
||||
@JsonKey(toJson: Serialization.readOnly)
|
||||
final DateTime pinnedAt;
|
||||
final DateTime? pinnedAt;
|
||||
|
||||
/// Reserved field indicating when the message will expire
|
||||
///
|
||||
/// if `null` message has no expiry
|
||||
final DateTime pinExpires;
|
||||
final DateTime? pinExpires;
|
||||
|
||||
/// Reserved field indicating who pinned the message
|
||||
@JsonKey(toJson: Serialization.readOnly)
|
||||
final User pinnedBy;
|
||||
final User? pinnedBy;
|
||||
|
||||
/// Message custom extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, dynamic> extraData;
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
defaultValue: {},
|
||||
)
|
||||
final Map<String, Object> extraData;
|
||||
|
||||
/// True if the message is a system info
|
||||
bool get isSystem => type == 'system';
|
||||
@@ -199,7 +221,7 @@ class Message extends Equatable {
|
||||
|
||||
/// Reserved field indicating when the message was deleted.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime deletedAt;
|
||||
final DateTime? deletedAt;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
@@ -236,39 +258,40 @@ class Message extends Equatable {
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$MessageToJson(this), topLevelFields);
|
||||
_$MessageToJson(this),
|
||||
);
|
||||
|
||||
/// Creates a copy of [Message] with specified attributes overridden.
|
||||
Message copyWith({
|
||||
String id,
|
||||
String text,
|
||||
String type,
|
||||
List<Attachment> attachments,
|
||||
List<User> mentionedUsers,
|
||||
Map<String, int> reactionCounts,
|
||||
Map<String, int> reactionScores,
|
||||
List<Reaction> latestReactions,
|
||||
List<Reaction> ownReactions,
|
||||
String parentId,
|
||||
Message quotedMessage,
|
||||
String quotedMessageId,
|
||||
int replyCount,
|
||||
List<User> threadParticipants,
|
||||
bool showInChannel,
|
||||
bool shadowed,
|
||||
bool silent,
|
||||
String command,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
DateTime deletedAt,
|
||||
User user,
|
||||
bool pinned,
|
||||
DateTime pinnedAt,
|
||||
Object pinExpires = _pinExpires,
|
||||
User pinnedBy,
|
||||
Map<String, dynamic> extraData,
|
||||
MessageSendingStatus status,
|
||||
bool skipPush,
|
||||
String? id,
|
||||
String? text,
|
||||
String? type,
|
||||
List<Attachment>? attachments,
|
||||
List<User>? mentionedUsers,
|
||||
Map<String, int>? reactionCounts,
|
||||
Map<String, int>? reactionScores,
|
||||
List<Reaction>? latestReactions,
|
||||
List<Reaction>? ownReactions,
|
||||
String? parentId,
|
||||
Message? quotedMessage,
|
||||
String? quotedMessageId,
|
||||
int? replyCount,
|
||||
List<User>? threadParticipants,
|
||||
bool? showInChannel,
|
||||
bool? shadowed,
|
||||
bool? silent,
|
||||
String? command,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? deletedAt,
|
||||
User? user,
|
||||
bool? pinned,
|
||||
DateTime? pinnedAt,
|
||||
Object? pinExpires = _pinExpires,
|
||||
User? pinnedBy,
|
||||
Map<String, Object>? extraData,
|
||||
MessageSendingStatus? status,
|
||||
bool? skipPush,
|
||||
}) {
|
||||
assert(() {
|
||||
if (pinExpires is! DateTime &&
|
||||
@@ -306,49 +329,47 @@ class Message extends Equatable {
|
||||
pinned: pinned ?? this.pinned,
|
||||
pinnedAt: pinnedAt ?? this.pinnedAt,
|
||||
pinnedBy: pinnedBy ?? this.pinnedBy,
|
||||
pinExpires: pinExpires == _pinExpires ? this.pinExpires : pinExpires,
|
||||
pinExpires:
|
||||
pinExpires == _pinExpires ? this.pinExpires : pinExpires as DateTime?,
|
||||
skipPush: skipPush ?? this.skipPush,
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns a new [Message] that is a combination of this message and the
|
||||
/// given [other] message.
|
||||
Message merge(Message other) {
|
||||
if (other == null) return this;
|
||||
return copyWith(
|
||||
id: other.id,
|
||||
text: other.text,
|
||||
type: other.type,
|
||||
attachments: other.attachments,
|
||||
mentionedUsers: other.mentionedUsers,
|
||||
reactionCounts: other.reactionCounts,
|
||||
reactionScores: other.reactionScores,
|
||||
latestReactions: other.latestReactions,
|
||||
ownReactions: other.ownReactions,
|
||||
parentId: other.parentId,
|
||||
quotedMessage: other.quotedMessage,
|
||||
quotedMessageId: other.quotedMessageId,
|
||||
replyCount: other.replyCount,
|
||||
threadParticipants: other.threadParticipants,
|
||||
showInChannel: other.showInChannel,
|
||||
command: other.command,
|
||||
createdAt: other.createdAt,
|
||||
silent: other.silent,
|
||||
extraData: other.extraData,
|
||||
user: other.user,
|
||||
shadowed: other.shadowed,
|
||||
updatedAt: other.updatedAt,
|
||||
deletedAt: other.deletedAt,
|
||||
status: other.status,
|
||||
pinned: other.pinned,
|
||||
pinnedAt: other.pinnedAt,
|
||||
pinExpires: other.pinExpires,
|
||||
pinnedBy: other.pinnedBy,
|
||||
);
|
||||
}
|
||||
Message merge(Message other) => copyWith(
|
||||
id: other.id,
|
||||
text: other.text,
|
||||
type: other.type,
|
||||
attachments: other.attachments,
|
||||
mentionedUsers: other.mentionedUsers,
|
||||
reactionCounts: other.reactionCounts,
|
||||
reactionScores: other.reactionScores,
|
||||
latestReactions: other.latestReactions,
|
||||
ownReactions: other.ownReactions,
|
||||
parentId: other.parentId,
|
||||
quotedMessage: other.quotedMessage,
|
||||
quotedMessageId: other.quotedMessageId,
|
||||
replyCount: other.replyCount,
|
||||
threadParticipants: other.threadParticipants,
|
||||
showInChannel: other.showInChannel,
|
||||
command: other.command,
|
||||
createdAt: other.createdAt,
|
||||
silent: other.silent,
|
||||
extraData: other.extraData,
|
||||
user: other.user,
|
||||
shadowed: other.shadowed,
|
||||
updatedAt: other.updatedAt,
|
||||
deletedAt: other.deletedAt,
|
||||
status: other.status,
|
||||
pinned: other.pinned,
|
||||
pinnedAt: other.pinnedAt,
|
||||
pinExpires: other.pinExpires,
|
||||
pinnedBy: other.pinnedBy,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
text,
|
||||
type,
|
||||
@@ -386,7 +407,7 @@ class Message extends Equatable {
|
||||
@JsonSerializable()
|
||||
class TranslatedMessage extends Message {
|
||||
/// Constructor used for json serialization
|
||||
TranslatedMessage(this.i18n);
|
||||
TranslatedMessage(this.i18n) : super();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory TranslatedMessage.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -395,7 +416,7 @@ class TranslatedMessage extends Message {
|
||||
);
|
||||
|
||||
/// A Map of
|
||||
final Map<String, String> i18n;
|
||||
final Map<String, String>? i18n;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
@@ -408,6 +429,5 @@ class TranslatedMessage extends Message {
|
||||
@override
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$TranslatedMessageToJson(this),
|
||||
topLevelFields,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,64 +6,44 @@ part of 'message.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Message _$MessageFromJson(Map json) {
|
||||
Message _$MessageFromJson(Map<String, dynamic> json) {
|
||||
return Message(
|
||||
id: json['id'] as String,
|
||||
text: json['text'] as String,
|
||||
type: json['type'] as String,
|
||||
attachments: (json['attachments'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Attachment.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
mentionedUsers: (json['mentioned_users'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: User.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
silent: json['silent'] as bool,
|
||||
shadowed: json['shadowed'] as bool,
|
||||
reactionCounts: (json['reaction_counts'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e as int),
|
||||
id: json['id'] as String?,
|
||||
text: json['text'] as String?,
|
||||
type: json['type'] as String? ?? 'regular',
|
||||
attachments: (json['attachments'] as List<dynamic>?)
|
||||
?.map((e) => Attachment.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
mentionedUsers: (json['mentioned_users'] as List<dynamic>?)
|
||||
?.map((e) => User.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
silent: json['silent'] as bool? ?? false,
|
||||
shadowed: json['shadowed'] as bool? ?? false,
|
||||
reactionCounts: (json['reaction_counts'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, e as int),
|
||||
),
|
||||
reactionScores: (json['reaction_scores'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e as int),
|
||||
reactionScores: (json['reaction_scores'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, e as int),
|
||||
),
|
||||
latestReactions: (json['latest_reactions'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Reaction.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
ownReactions: (json['own_reactions'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Reaction.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
parentId: json['parent_id'] as String,
|
||||
latestReactions: (json['latest_reactions'] as List<dynamic>?)
|
||||
?.map((e) => Reaction.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
ownReactions: (json['own_reactions'] as List<dynamic>?)
|
||||
?.map((e) => Reaction.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
parentId: json['parent_id'] as String?,
|
||||
quotedMessage: json['quoted_message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['quoted_message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
quotedMessageId: json['quoted_message_id'] as String,
|
||||
replyCount: json['reply_count'] as int,
|
||||
threadParticipants: (json['thread_participants'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: User.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
showInChannel: json['show_in_channel'] as bool,
|
||||
command: json['command'] as String,
|
||||
: Message.fromJson(json['quoted_message'] as Map<String, dynamic>),
|
||||
quotedMessageId: json['quoted_message_id'] as String?,
|
||||
replyCount: json['reply_count'] as int?,
|
||||
threadParticipants: (json['thread_participants'] as List<dynamic>?)
|
||||
?.map((e) => User.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
showInChannel: json['show_in_channel'] as bool?,
|
||||
command: json['command'] as String?,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
@@ -72,10 +52,8 @@ Message _$MessageFromJson(Map json) {
|
||||
: DateTime.parse(json['updated_at'] as String),
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
pinned: json['pinned'] as bool,
|
||||
: User.fromJson(json['user'] as Map<String, dynamic>),
|
||||
pinned: json['pinned'] as bool? ?? false,
|
||||
pinnedAt: json['pinned_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['pinned_at'] as String),
|
||||
@@ -84,16 +62,15 @@ Message _$MessageFromJson(Map json) {
|
||||
: DateTime.parse(json['pin_expires'] as String),
|
||||
pinnedBy: json['pinned_by'] == null
|
||||
? null
|
||||
: User.fromJson((json['pinned_by'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
),
|
||||
: User.fromJson(json['pinned_by'] as Map<String, dynamic>),
|
||||
extraData: (json['extra_data'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, e as Object),
|
||||
) ??
|
||||
{},
|
||||
deletedAt: json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
skipPush: json['skip_push'] as bool,
|
||||
skipPush: json['skip_push'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -110,8 +87,7 @@ Map<String, dynamic> _$MessageToJson(Message instance) {
|
||||
}
|
||||
|
||||
writeNotNull('type', readonly(instance.type));
|
||||
writeNotNull(
|
||||
'attachments', instance.attachments?.map((e) => e?.toJson())?.toList());
|
||||
val['attachments'] = instance.attachments.map((e) => e.toJson()).toList();
|
||||
val['mentioned_users'] = Serialization.userIds(instance.mentionedUsers);
|
||||
writeNotNull('reaction_counts', readonly(instance.reactionCounts));
|
||||
writeNotNull('reaction_scores', readonly(instance.reactionScores));
|
||||
@@ -134,15 +110,15 @@ Map<String, dynamic> _$MessageToJson(Message instance) {
|
||||
val['pinned_at'] = readonly(instance.pinnedAt);
|
||||
val['pin_expires'] = instance.pinExpires?.toIso8601String();
|
||||
val['pinned_by'] = readonly(instance.pinnedBy);
|
||||
writeNotNull('extra_data', instance.extraData);
|
||||
val['extra_data'] = instance.extraData;
|
||||
writeNotNull('deleted_at', readonly(instance.deletedAt));
|
||||
return val;
|
||||
}
|
||||
|
||||
TranslatedMessage _$TranslatedMessageFromJson(Map json) {
|
||||
TranslatedMessage _$TranslatedMessageFromJson(Map<String, dynamic> json) {
|
||||
return TranslatedMessage(
|
||||
(json['i18n'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e as String),
|
||||
(json['i18n'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, e as String),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,12 @@ part 'mute.g.dart';
|
||||
@JsonSerializable()
|
||||
class Mute {
|
||||
/// Constructor used for json serialization
|
||||
Mute({this.user, this.channel, this.createdAt, this.updatedAt});
|
||||
Mute({
|
||||
required this.user,
|
||||
required this.channel,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Mute.fromJson(Map<String, dynamic> json) => _$MuteFromJson(json);
|
||||
|
||||
@@ -6,24 +6,12 @@ part of 'mute.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Mute _$MuteFromJson(Map json) {
|
||||
Mute _$MuteFromJson(Map<String, dynamic> json) {
|
||||
return Mute(
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
channel: json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: json['updated_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['updated_at'] as String),
|
||||
user: User.fromJson(json['user'] as Map<String, dynamic>),
|
||||
channel: ChannelModel.fromJson(json['channel'] as Map<String, dynamic>),
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,19 +12,19 @@ part 'own_user.g.dart';
|
||||
class OwnUser extends User {
|
||||
/// Constructor used for json serialization
|
||||
OwnUser({
|
||||
this.devices,
|
||||
this.mutes,
|
||||
this.totalUnreadCount,
|
||||
this.devices = const [],
|
||||
this.mutes = const [],
|
||||
this.totalUnreadCount = 0,
|
||||
this.unreadChannels,
|
||||
this.channelMutes,
|
||||
String id,
|
||||
String role,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
DateTime lastActive,
|
||||
bool online,
|
||||
Map<String, dynamic> extraData,
|
||||
bool banned,
|
||||
this.channelMutes = const [],
|
||||
required String id,
|
||||
String? role,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? lastActive,
|
||||
bool online = false,
|
||||
Map<String, Object> extraData = const {},
|
||||
bool banned = false,
|
||||
}) : super(
|
||||
id: id,
|
||||
role: role,
|
||||
@@ -41,24 +41,34 @@ class OwnUser extends User {
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields));
|
||||
|
||||
/// List of user devices
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serialization.readOnly,
|
||||
defaultValue: <Device>[])
|
||||
final List<Device> devices;
|
||||
|
||||
/// List of users muted by the user
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serialization.readOnly,
|
||||
defaultValue: <Mute>[])
|
||||
final List<Mute> mutes;
|
||||
|
||||
/// List of users muted by the user
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serialization.readOnly,
|
||||
defaultValue: <Mute>[])
|
||||
final List<Mute> channelMutes;
|
||||
|
||||
/// Total unread messages by the user
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false, toJson: Serialization.readOnly, defaultValue: 0)
|
||||
final int totalUnreadCount;
|
||||
|
||||
/// Total unread channels by the user
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final int unreadChannels;
|
||||
final int? unreadChannels;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
@@ -74,5 +84,6 @@ class OwnUser extends User {
|
||||
/// Serialize to json
|
||||
@override
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$OwnUserToJson(this), topLevelFields);
|
||||
_$OwnUserToJson(this),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,33 +6,24 @@ part of 'own_user.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
OwnUser _$OwnUserFromJson(Map json) {
|
||||
OwnUser _$OwnUserFromJson(Map<String, dynamic> json) {
|
||||
return OwnUser(
|
||||
devices: (json['devices'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Device.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
mutes: (json['mutes'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Mute.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
totalUnreadCount: json['total_unread_count'] as int,
|
||||
unreadChannels: json['unread_channels'] as int,
|
||||
channelMutes: (json['channel_mutes'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Mute.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
devices: (json['devices'] as List<dynamic>?)
|
||||
?.map((e) => Device.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
mutes: (json['mutes'] as List<dynamic>?)
|
||||
?.map((e) => Mute.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
totalUnreadCount: json['total_unread_count'] as int? ?? 0,
|
||||
unreadChannels: json['unread_channels'] as int?,
|
||||
channelMutes: (json['channel_mutes'] as List<dynamic>?)
|
||||
?.map((e) => Mute.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
id: json['id'] as String,
|
||||
role: json['role'] as String,
|
||||
role: json['role'] as String?,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
@@ -42,11 +33,11 @@ OwnUser _$OwnUserFromJson(Map json) {
|
||||
lastActive: json['last_active'] == null
|
||||
? null
|
||||
: DateTime.parse(json['last_active'] as String),
|
||||
online: json['online'] as bool,
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
online: json['online'] as bool? ?? false,
|
||||
extraData: (json['extra_data'] as Map<String, dynamic>).map(
|
||||
(k, e) => MapEntry(k, e as Object),
|
||||
),
|
||||
banned: json['banned'] as bool,
|
||||
banned: json['banned'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -67,7 +58,7 @@ Map<String, dynamic> _$OwnUserToJson(OwnUser instance) {
|
||||
writeNotNull('last_active', readonly(instance.lastActive));
|
||||
writeNotNull('online', readonly(instance.online));
|
||||
writeNotNull('banned', readonly(instance.banned));
|
||||
writeNotNull('extra_data', instance.extraData);
|
||||
val['extra_data'] = instance.extraData;
|
||||
writeNotNull('devices', readonly(instance.devices));
|
||||
writeNotNull('mutes', readonly(instance.mutes));
|
||||
writeNotNull('channel_mutes', readonly(instance.channelMutes));
|
||||
|
||||
@@ -10,20 +10,24 @@ class Reaction {
|
||||
/// Constructor used for json serialization
|
||||
Reaction({
|
||||
this.messageId,
|
||||
this.createdAt,
|
||||
this.type,
|
||||
DateTime? createdAt,
|
||||
required this.type,
|
||||
this.user,
|
||||
String userId,
|
||||
this.score,
|
||||
String? userId,
|
||||
this.score = 0,
|
||||
this.extraData,
|
||||
}) : userId = userId ?? user?.id;
|
||||
}) : userId = userId ?? user?.id,
|
||||
createdAt = createdAt ?? DateTime.now();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Reaction.fromJson(Map<String, dynamic> json) => _$ReactionFromJson(
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields));
|
||||
factory Reaction.fromJson(Map<String, dynamic> json) =>
|
||||
_$ReactionFromJson(Serialization.moveToExtraDataFromRoot(
|
||||
json,
|
||||
topLevelFields,
|
||||
));
|
||||
|
||||
/// The messageId to which the reaction belongs
|
||||
final String messageId;
|
||||
final String? messageId;
|
||||
|
||||
/// The type of the reaction
|
||||
final String type;
|
||||
@@ -34,18 +38,19 @@ class Reaction {
|
||||
|
||||
/// The user that sent the reaction
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final User user;
|
||||
final User? user;
|
||||
|
||||
/// The score of the reaction (ie. number of reactions sent)
|
||||
@JsonKey(defaultValue: 0)
|
||||
final int score;
|
||||
|
||||
/// The userId that sent the reaction
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final String userId;
|
||||
final String? userId;
|
||||
|
||||
/// Reaction custom extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, dynamic> extraData;
|
||||
final Map<String, Object>? extraData;
|
||||
|
||||
/// Map of custom user extraData
|
||||
static const topLevelFields = [
|
||||
@@ -59,17 +64,18 @@ class Reaction {
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$ReactionToJson(this), topLevelFields);
|
||||
_$ReactionToJson(this),
|
||||
);
|
||||
|
||||
/// Creates a copy of [Reaction] with specified attributes overridden.
|
||||
Reaction copyWith({
|
||||
String messageId,
|
||||
DateTime createdAt,
|
||||
String type,
|
||||
User user,
|
||||
String userId,
|
||||
int score,
|
||||
Map<String, dynamic> extraData,
|
||||
String? messageId,
|
||||
DateTime? createdAt,
|
||||
String? type,
|
||||
User? user,
|
||||
String? userId,
|
||||
int? score,
|
||||
Map<String, Object>? extraData,
|
||||
}) =>
|
||||
Reaction(
|
||||
messageId: messageId ?? this.messageId,
|
||||
@@ -83,16 +89,13 @@ class Reaction {
|
||||
|
||||
/// Returns a new [Reaction] that is a combination of this reaction and the
|
||||
/// given [other] reaction.
|
||||
Reaction merge(Reaction other) {
|
||||
if (other == null) return this;
|
||||
return copyWith(
|
||||
messageId: other.messageId,
|
||||
createdAt: other.createdAt,
|
||||
type: other.type,
|
||||
user: other.user,
|
||||
userId: other.userId,
|
||||
score: other.score,
|
||||
extraData: other.extraData,
|
||||
);
|
||||
}
|
||||
Reaction merge(Reaction other) => copyWith(
|
||||
messageId: other.messageId,
|
||||
createdAt: other.createdAt,
|
||||
type: other.type,
|
||||
user: other.user,
|
||||
userId: other.userId,
|
||||
score: other.score,
|
||||
extraData: other.extraData,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,22 +6,20 @@ part of 'reaction.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Reaction _$ReactionFromJson(Map json) {
|
||||
Reaction _$ReactionFromJson(Map<String, dynamic> json) {
|
||||
return Reaction(
|
||||
messageId: json['message_id'] as String,
|
||||
messageId: json['message_id'] as String?,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
type: json['type'] as String,
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
userId: json['user_id'] as String,
|
||||
score: json['score'] as int,
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
: User.fromJson(json['user'] as Map<String, dynamic>),
|
||||
userId: json['user_id'] as String?,
|
||||
score: json['score'] as int? ?? 0,
|
||||
extraData: (json['extra_data'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, e as Object),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ part 'read.g.dart';
|
||||
class Read {
|
||||
/// Constructor used for json serialization
|
||||
Read({
|
||||
this.lastRead,
|
||||
this.user,
|
||||
this.unreadMessages,
|
||||
required this.lastRead,
|
||||
required this.user,
|
||||
this.unreadMessages = 0,
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
@@ -23,6 +23,7 @@ class Read {
|
||||
final User user;
|
||||
|
||||
/// Number of unread messages
|
||||
@JsonKey(defaultValue: 0)
|
||||
final int unreadMessages;
|
||||
|
||||
/// Serialize to json
|
||||
@@ -30,9 +31,9 @@ class Read {
|
||||
|
||||
/// Creates a copy of [Read] with specified attributes overridden.
|
||||
Read copyWith({
|
||||
DateTime lastRead,
|
||||
User user,
|
||||
int unreadMessages,
|
||||
DateTime? lastRead,
|
||||
User? user,
|
||||
int? unreadMessages,
|
||||
}) =>
|
||||
Read(
|
||||
lastRead: lastRead ?? this.lastRead,
|
||||
|
||||
@@ -6,22 +6,16 @@ part of 'read.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Read _$ReadFromJson(Map json) {
|
||||
Read _$ReadFromJson(Map<String, dynamic> json) {
|
||||
return Read(
|
||||
lastRead: json['last_read'] == null
|
||||
? null
|
||||
: DateTime.parse(json['last_read'] as String),
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
unreadMessages: json['unread_messages'] as int,
|
||||
lastRead: DateTime.parse(json['last_read'] as String),
|
||||
user: User.fromJson(json['user'] as Map<String, dynamic>),
|
||||
unreadMessages: json['unread_messages'] as int? ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$ReadToJson(Read instance) => <String, dynamic>{
|
||||
'last_read': instance.lastRead?.toIso8601String(),
|
||||
'user': instance.user?.toJson(),
|
||||
'last_read': instance.lastRead.toIso8601String(),
|
||||
'user': instance.user.toJson(),
|
||||
'unread_messages': instance.unreadMessages,
|
||||
};
|
||||
|
||||
@@ -10,16 +10,14 @@ class Serialization {
|
||||
static const Function readOnly = readonly;
|
||||
|
||||
/// List of users to list of userIds
|
||||
static List<String> userIds(List<User> users) =>
|
||||
users?.map((u) => u.id)?.toList();
|
||||
static List<String>? userIds(List<User>? users) =>
|
||||
users?.map((u) => u.id).toList();
|
||||
|
||||
/// Takes unknown json keys and puts them in the `extra_data` key
|
||||
static Map<String, dynamic> moveToExtraDataFromRoot(
|
||||
Map<String, dynamic> json,
|
||||
List<String> topLevelFields,
|
||||
) {
|
||||
if (json == null) return null;
|
||||
|
||||
final jsonClone = Map<String, dynamic>.from(json);
|
||||
|
||||
final extraDataMap = Map<String, dynamic>.from(json)
|
||||
@@ -38,7 +36,6 @@ class Serialization {
|
||||
/// the json map
|
||||
static Map<String, dynamic> moveFromExtraDataToRoot(
|
||||
Map<String, dynamic> json,
|
||||
List<String> topLevelFields,
|
||||
) {
|
||||
final jsonClone = Map<String, dynamic>.from(json);
|
||||
return jsonClone
|
||||
|
||||
@@ -8,33 +8,22 @@ part 'user.g.dart';
|
||||
class User {
|
||||
/// Constructor used for json serialization
|
||||
User({
|
||||
this.id,
|
||||
required this.id,
|
||||
this.role,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
this.lastActive,
|
||||
this.online,
|
||||
this.extraData,
|
||||
this.banned,
|
||||
this.teams,
|
||||
});
|
||||
this.online = false,
|
||||
this.extraData = const {},
|
||||
this.banned = false,
|
||||
this.teams = const [],
|
||||
}) : createdAt = createdAt ?? DateTime.now(),
|
||||
updatedAt = updatedAt ?? DateTime.now();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields));
|
||||
|
||||
/// Use this named constructor to create a new user instance
|
||||
User.init(
|
||||
this.id, {
|
||||
this.online,
|
||||
this.extraData,
|
||||
}) : createdAt = null,
|
||||
updatedAt = null,
|
||||
lastActive = null,
|
||||
banned = null,
|
||||
teams = null,
|
||||
role = null;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
static const topLevelFields = [
|
||||
@@ -53,10 +42,13 @@ class User {
|
||||
|
||||
/// User role
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final String role;
|
||||
final String? role;
|
||||
|
||||
/// User role
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serialization.readOnly,
|
||||
defaultValue: <String>[])
|
||||
final List<String> teams;
|
||||
|
||||
/// Date of user creation
|
||||
@@ -69,28 +61,33 @@ class User {
|
||||
|
||||
/// Date of last user connection
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime lastActive;
|
||||
final DateTime? lastActive;
|
||||
|
||||
/// True if user is online
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false, toJson: Serialization.readOnly, defaultValue: false)
|
||||
final bool online;
|
||||
|
||||
/// True if user is banned from the chat
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false, toJson: Serialization.readOnly, defaultValue: false)
|
||||
final bool banned;
|
||||
|
||||
/// Map of custom user extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, dynamic> extraData;
|
||||
final Map<String, Object> extraData;
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
|
||||
/// Shortcut for user name
|
||||
String get name =>
|
||||
(extraData?.containsKey('name') == true && extraData['name'] != '')
|
||||
? extraData['name']
|
||||
: id;
|
||||
String get name {
|
||||
if (extraData.containsKey('name')) {
|
||||
final name = extraData['name'] as String;
|
||||
if (name.isNotEmpty) return name;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
@@ -98,20 +95,21 @@ class User {
|
||||
other is User && runtimeType == other.runtimeType && id == other.id;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() =>
|
||||
Serialization.moveFromExtraDataToRoot(_$UserToJson(this), topLevelFields);
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$UserToJson(this),
|
||||
);
|
||||
|
||||
/// Creates a copy of [User] with specified attributes overridden.
|
||||
User copyWith({
|
||||
String id,
|
||||
String role,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
DateTime lastActive,
|
||||
bool online,
|
||||
Map<String, dynamic> extraData,
|
||||
bool banned,
|
||||
List<String> teams,
|
||||
String? id,
|
||||
String? role,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? lastActive,
|
||||
bool? online,
|
||||
Map<String, Object>? extraData,
|
||||
bool? banned,
|
||||
List<String>? teams,
|
||||
}) =>
|
||||
User(
|
||||
id: id ?? this.id,
|
||||
|
||||
@@ -6,10 +6,10 @@ part of 'user.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
User _$UserFromJson(Map json) {
|
||||
User _$UserFromJson(Map<String, dynamic> json) {
|
||||
return User(
|
||||
id: json['id'] as String,
|
||||
role: json['role'] as String,
|
||||
role: json['role'] as String?,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
@@ -19,12 +19,14 @@ User _$UserFromJson(Map json) {
|
||||
lastActive: json['last_active'] == null
|
||||
? null
|
||||
: DateTime.parse(json['last_active'] as String),
|
||||
online: json['online'] as bool,
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
online: json['online'] as bool? ?? false,
|
||||
extraData: (json['extra_data'] as Map<String, dynamic>).map(
|
||||
(k, e) => MapEntry(k, e as Object),
|
||||
),
|
||||
banned: json['banned'] as bool,
|
||||
teams: (json['teams'] as List)?.map((e) => e as String)?.toList(),
|
||||
banned: json['banned'] as bool? ?? false,
|
||||
teams:
|
||||
(json['teams'] as List<dynamic>?)?.map((e) => e as String).toList() ??
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -46,6 +48,6 @@ Map<String, dynamic> _$UserToJson(User instance) {
|
||||
writeNotNull('last_active', readonly(instance.lastActive));
|
||||
writeNotNull('online', readonly(instance.online));
|
||||
writeNotNull('banned', readonly(instance.banned));
|
||||
writeNotNull('extra_data', instance.extraData);
|
||||
val['extra_data'] = instance.extraData;
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ library stream_chat;
|
||||
export 'package:async/async.dart';
|
||||
export 'package:dio/src/dio_error.dart';
|
||||
export 'package:dio/src/multipart_file.dart';
|
||||
export 'package:dio/src/options.dart';
|
||||
export 'package:dio/src/options.dart' show ProgressCallback;
|
||||
export 'package:logging/logging.dart' show Logger, Level;
|
||||
|
||||
@@ -27,6 +28,7 @@ export './src/models/channel_state.dart';
|
||||
export './src/models/command.dart';
|
||||
export './src/models/device.dart';
|
||||
export './src/models/event.dart';
|
||||
export './src/models/filter.dart' show Filter;
|
||||
export './src/models/member.dart';
|
||||
export './src/models/message.dart';
|
||||
export './src/models/mute.dart';
|
||||
|
||||
@@ -3,4 +3,4 @@ import 'package:stream_chat/src/client.dart';
|
||||
/// Current package version
|
||||
/// Used in [StreamChatClient] to build the `x-stream-client` header
|
||||
// ignore: constant_identifier_names
|
||||
const PACKAGE_VERSION = '1.5.3';
|
||||
const PACKAGE_VERSION = '2.0.0-nullsafety.0';
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
name: stream_chat
|
||||
homepage: https://getstream.io/
|
||||
description: The official Dart client for Stream Chat, a service for building chat applications.
|
||||
version: 1.5.3
|
||||
version: 2.0.0-nullsafety.0
|
||||
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.4.2
|
||||
collection: ^1.14.13
|
||||
dio: ^3.0.10
|
||||
async: ^2.5.0
|
||||
collection: ^1.15.0
|
||||
dio: ^4.0.0
|
||||
equatable: ^2.0.0
|
||||
freezed_annotation: ^0.12.0
|
||||
http_parser: ^3.1.4
|
||||
json_annotation: ^3.0.1
|
||||
logging: ^0.11.4
|
||||
meta: ^1.2.4
|
||||
mime: ^0.9.7
|
||||
rxdart: ^0.25.0
|
||||
uuid: ^2.2.2
|
||||
web_socket_channel: ^1.2.0
|
||||
freezed_annotation: ^0.14.0
|
||||
http_parser: ^4.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.4
|
||||
web_socket_channel: ^2.0.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^1.10.0
|
||||
freezed: ^0.12.7
|
||||
json_serializable: ^3.3.0
|
||||
mockito: ^4.1.1
|
||||
test: ^1.15.7
|
||||
build_runner: ^2.0.1
|
||||
freezed: ^0.14.1+3
|
||||
json_serializable: ^4.1.0
|
||||
mocktail: ^0.1.1
|
||||
test: ^1.16.8
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,19 @@
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/api/requests', () {
|
||||
test('SortOption', () {
|
||||
final option = SortOption('name');
|
||||
const option = SortOption('name');
|
||||
final j = option.toJson();
|
||||
expect(j, {'field': 'name', 'direction': -1});
|
||||
});
|
||||
|
||||
test('PaginationParams', () {
|
||||
final option = PaginationParams();
|
||||
const option = PaginationParams();
|
||||
final j = option.toJson();
|
||||
expect(j, {'limit': 10, 'offset': 0});
|
||||
expect(j, containsPair('limit', 10));
|
||||
expect(j, containsPair('offset', 0));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ import 'package:stream_chat/stream_chat.dart';
|
||||
void main() {
|
||||
group('src/api/responses', () {
|
||||
test('QueryChannelsResponse', () {
|
||||
const jsonExample = r'''{
|
||||
const jsonExample = r'''
|
||||
{
|
||||
"channels": [
|
||||
{
|
||||
"channel": {
|
||||
@@ -3284,7 +3285,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('QueryReactionsResponse', () {
|
||||
const jsonExample = r'''
|
||||
const jsonExample = '''
|
||||
{"reactions": [{"message_id": "4637f7e4-a06b-42db-ba5a-8d8270dd926f","user_id": "c1c9b454-2bcc-402d-8bb0-2f3706ce1680","user": {"id": "c1c9b454-2bcc-402d-8bb0-2f3706ce1680","role": "user","created_at": "2020-01-28T22:17:30.83015Z","updated_at": "2020-01-28T22:17:31.19435Z","banned": false,"online": false,"image": "https://randomuser.me/api/portraits/women/2.jpg","name": "Mia Denys"},"type": "love","score": 1,"created_at": "2020-01-28T22:17:31.128376Z","updated_at": "2020-01-28T22:17:31.128376Z"}]}
|
||||
''';
|
||||
final response =
|
||||
@@ -3402,37 +3403,38 @@ void main() {
|
||||
|
||||
test('ListDevicesResponse', () {
|
||||
const jsonExample =
|
||||
r'''{"devices":[{"push_provider":"firebase","id":"test"}],"duration":"0.35ms"}''';
|
||||
'''{"devices":[{"push_provider":"firebase","id":"test"}],"duration":"0.35ms"}''';
|
||||
final response = ListDevicesResponse.fromJson(json.decode(jsonExample));
|
||||
expect(response.devices, isA<List<Device>>());
|
||||
});
|
||||
|
||||
test('SendFileResponse', () {
|
||||
const jsonExample = r'''{"file": "file-url","duration":"0.35ms"}''';
|
||||
const jsonExample = '''{"file": "file-url","duration":"0.35ms"}''';
|
||||
final response = SendFileResponse.fromJson(json.decode(jsonExample));
|
||||
expect(response.file, isA<String>());
|
||||
});
|
||||
|
||||
test('SendImageResponse', () {
|
||||
const jsonExample = r'''{"file": "file-url","duration":"0.35ms"}''';
|
||||
const jsonExample = '''{"file": "file-url","duration":"0.35ms"}''';
|
||||
final response = SendImageResponse.fromJson(json.decode(jsonExample));
|
||||
expect(response.file, isA<String>());
|
||||
});
|
||||
|
||||
test('SendImageResponse', () {
|
||||
const jsonExample = r'''{"file": "file-url","duration":"0.35ms"}''';
|
||||
const jsonExample = '''{"file": "file-url","duration":"0.35ms"}''';
|
||||
final response = SendImageResponse.fromJson(json.decode(jsonExample));
|
||||
expect(response.file, isA<String>());
|
||||
});
|
||||
|
||||
test('EmptyResponse', () {
|
||||
const jsonExample = r'''{"file": "file-url","duration":"0.35ms"}''';
|
||||
const jsonExample = '''{"file": "file-url","duration":"0.35ms"}''';
|
||||
final response = EmptyResponse.fromJson(json.decode(jsonExample));
|
||||
expect(response.duration, isA<String>());
|
||||
});
|
||||
|
||||
test('SendReactionResponse', () {
|
||||
const jsonExample = r'''{"message": {
|
||||
const jsonExample = r'''
|
||||
{"message": {
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3481,8 +3483,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('UpdateUsersResponse', () {
|
||||
const jsonExample =
|
||||
r'''{"users": {"bbb19d9a-ee50-45bc-84e5-0584e79d0c9e":{
|
||||
const jsonExample = '''
|
||||
{"users": {"bbb19d9a-ee50-45bc-84e5-0584e79d0c9e":{
|
||||
"id": "bbb19d9a-ee50-45bc-84e5-0584e79d0c9e",
|
||||
"role": "user",
|
||||
"created_at": "2020-01-28T22:17:30.826259Z",
|
||||
@@ -3498,7 +3500,7 @@ void main() {
|
||||
|
||||
test('ConnectGuestUserResponse', () {
|
||||
const jsonExample =
|
||||
r'{"user":{"id":"guest-ac612aee-25fe-49fb-b1af-969e41f452a0-wild-breeze-7","role":"guest","created_at":"2020-02-03T10:19:01.538434Z","updated_at":"2020-02-03T10:19:01.539543Z","banned":false,"online":false},"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZ3Vlc3QtYWM2MTJhZWUtMjVmZS00OWZiLWIxYWYtOTY5ZTQxZjQ1MmEwLXdpbGQtYnJlZXplLTcifQ.mmoFGu7oJjpFsp7nFN78UbIpO7gowbuIbyoppsuvbXA","duration":"4.66ms"}';
|
||||
'''{"user":{"id":"guest-ac612aee-25fe-49fb-b1af-969e41f452a0-wild-breeze-7","role":"guest","created_at":"2020-02-03T10:19:01.538434Z","updated_at":"2020-02-03T10:19:01.539543Z","banned":false,"online":false},"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZ3Vlc3QtYWM2MTJhZWUtMjVmZS00OWZiLWIxYWYtOTY5ZTQxZjQ1MmEwLXdpbGQtYnJlZXplLTcifQ.mmoFGu7oJjpFsp7nFN78UbIpO7gowbuIbyoppsuvbXA","duration":"4.66ms"}''';
|
||||
final response =
|
||||
ConnectGuestUserResponse.fromJson(json.decode(jsonExample));
|
||||
expect(response.user, isA<User>());
|
||||
@@ -3506,7 +3508,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GetMessagesByIdResponse', () {
|
||||
const jsonExample = r'''{"messages":[{
|
||||
const jsonExample = r'''
|
||||
{"messages":[{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3537,7 +3540,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('SendActionResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3567,7 +3571,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('UpdateMessageResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3597,7 +3602,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('SendMessageResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3627,7 +3633,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GetMessageResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3657,7 +3664,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('UpdateChannelResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3770,7 +3778,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('InviteMembersResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3883,7 +3892,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('RemoveMembersResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3996,7 +4006,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('AddMembersResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -4109,7 +4120,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('AcceptInviteResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -4222,7 +4234,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('RejectInviteResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/api/web_socket_channel_stub.dart';
|
||||
|
||||
void main() {
|
||||
test('src/api/web_socket_stub_test', () {
|
||||
expect(
|
||||
() => connectWebSocket('fakeurl'),
|
||||
throwsA(isA<UnimplementedError>()),
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:stream_chat/src/api/connection_status.dart';
|
||||
import 'package:stream_chat/src/api/websocket.dart';
|
||||
import 'package:stream_chat/src/models/event.dart';
|
||||
@@ -12,14 +12,12 @@ 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) => null;
|
||||
void handleFunc(Event event) {}
|
||||
}
|
||||
|
||||
class MockFunctions extends Mock implements Functions {}
|
||||
@@ -28,35 +26,35 @@ class MockWSChannel extends Mock implements WebSocketChannel {}
|
||||
|
||||
class MockWSSink extends Mock implements WebSocketSink {}
|
||||
|
||||
class FakeEvent extends Fake implements Event {}
|
||||
|
||||
void main() {
|
||||
group('src/api/websocket', () {
|
||||
test('should connect with correct parameters', () async {
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
setUpAll(() {
|
||||
registerFallbackValue<Event>(FakeEvent());
|
||||
});
|
||||
|
||||
test('should connect with correct parameters', () async {
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
user: User(id: 'testid'),
|
||||
logger: Logger('ws'),
|
||||
connectParams: {'test': 'true'},
|
||||
connectPayload: {'payload': 'test'},
|
||||
handler: (e) {
|
||||
print(e);
|
||||
},
|
||||
handler: print,
|
||||
connectFunc: connectFunc,
|
||||
);
|
||||
|
||||
final mockWSChannel = MockWSChannel();
|
||||
|
||||
final streamController = StreamController<String>.broadcast();
|
||||
|
||||
const computedUrl =
|
||||
'wss://baseurl/connect?test=true&json=%7B%22payload%22%3A%22test%22%2C%22user_details%22%3A%7B%22id%22%3A%22testid%22%7D%7D';
|
||||
|
||||
when(connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(mockWSChannel.sink).thenAnswer((_) => MockWSSink());
|
||||
when(mockWSChannel.stream).thenAnswer((_) {
|
||||
return streamController.stream;
|
||||
});
|
||||
when(() => connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => MockWSSink());
|
||||
when(() => mockWSChannel.stream).thenAnswer(
|
||||
(_) => streamController.stream,
|
||||
);
|
||||
|
||||
final timer = Timer.periodic(
|
||||
const Duration(milliseconds: 100),
|
||||
@@ -65,7 +63,7 @@ void main() {
|
||||
|
||||
await ws.connect();
|
||||
|
||||
verify(connectFunc(computedUrl)).called(1);
|
||||
verify(() => connectFunc(computedUrl)).called(1);
|
||||
expect(ws.connectionStatus, ConnectionStatus.connected);
|
||||
|
||||
await streamController.close();
|
||||
@@ -75,8 +73,7 @@ void main() {
|
||||
|
||||
test('should connect with correct parameters and handle events', () async {
|
||||
final handleFunc = MockFunctions().handleFunc;
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
user: User(id: 'testid'),
|
||||
@@ -86,27 +83,21 @@ void main() {
|
||||
handler: handleFunc,
|
||||
connectFunc: connectFunc,
|
||||
);
|
||||
|
||||
final mockWSChannel = MockWSChannel();
|
||||
|
||||
final StreamController<String> streamController =
|
||||
StreamController<String>.broadcast();
|
||||
|
||||
final computedUrl =
|
||||
final streamController = StreamController<String>.broadcast();
|
||||
const computedUrl =
|
||||
'wss://baseurl/connect?test=true&json=%7B%22payload%22%3A%22test%22%2C%22user_details%22%3A%7B%22id%22%3A%22testid%22%7D%7D';
|
||||
|
||||
when(connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(mockWSChannel.sink).thenAnswer((_) => MockWSSink());
|
||||
when(mockWSChannel.stream).thenAnswer((_) {
|
||||
return streamController.stream;
|
||||
});
|
||||
when(() => connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => MockWSSink());
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
|
||||
final connect = ws.connect().then((_) {
|
||||
streamController.sink.add('{}');
|
||||
return Future.delayed(Duration(milliseconds: 200));
|
||||
return Future.delayed(const Duration(milliseconds: 200));
|
||||
}).then((value) {
|
||||
verify(connectFunc(computedUrl)).called(1);
|
||||
verify(handleFunc(any)).called(greaterThan(0));
|
||||
verify(() => connectFunc(computedUrl)).called(1);
|
||||
verify(() => handleFunc(any())).called(greaterThan(0));
|
||||
|
||||
return streamController.close();
|
||||
});
|
||||
@@ -118,9 +109,7 @@ void main() {
|
||||
|
||||
test('should close correctly the controller', () async {
|
||||
final handleFunc = MockFunctions().handleFunc;
|
||||
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
user: User(id: 'testid'),
|
||||
@@ -130,27 +119,23 @@ void main() {
|
||||
handler: handleFunc,
|
||||
connectFunc: connectFunc,
|
||||
);
|
||||
|
||||
final mockWSChannel = MockWSChannel();
|
||||
|
||||
final StreamController<String> streamController =
|
||||
StreamController<String>.broadcast();
|
||||
|
||||
final computedUrl =
|
||||
final streamController = StreamController<String>.broadcast();
|
||||
const computedUrl =
|
||||
'wss://baseurl/connect?test=true&json=%7B%22payload%22%3A%22test%22%2C%22user_details%22%3A%7B%22id%22%3A%22testid%22%7D%7D';
|
||||
|
||||
when(connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(mockWSChannel.sink).thenAnswer((_) => MockWSSink());
|
||||
when(mockWSChannel.stream).thenAnswer((_) {
|
||||
return streamController.stream;
|
||||
});
|
||||
final mockWSSink = MockWSSink();
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => mockWSSink);
|
||||
when(() => mockWSSink.close(any(), any())).thenAnswer((_) async => null);
|
||||
when(() => connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
|
||||
final connect = ws.connect().then((_) {
|
||||
streamController.sink.add('{}');
|
||||
return Future.delayed(Duration(milliseconds: 200));
|
||||
return Future.delayed(const Duration(milliseconds: 200));
|
||||
}).then((value) {
|
||||
verify(connectFunc(computedUrl)).called(1);
|
||||
verify(handleFunc(any)).called(greaterThan(0));
|
||||
verify(() => connectFunc(computedUrl)).called(1);
|
||||
verify(() => handleFunc(any())).called(greaterThan(0));
|
||||
|
||||
return streamController.close();
|
||||
});
|
||||
@@ -159,10 +144,11 @@ void main() {
|
||||
|
||||
return connect;
|
||||
});
|
||||
|
||||
test('should close correctly the controller while connecting', () async {
|
||||
final handleFunc = MockFunctions().handleFunc;
|
||||
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
@@ -176,31 +162,30 @@ void main() {
|
||||
|
||||
final mockWSChannel = MockWSChannel();
|
||||
|
||||
final StreamController<String> streamController =
|
||||
StreamController<String>.broadcast();
|
||||
final streamController = StreamController<String>.broadcast();
|
||||
|
||||
final computedUrl =
|
||||
const computedUrl =
|
||||
'wss://baseurl/connect?test=true&json=%7B%22payload%22%3A%22test%22%2C%22user_details%22%3A%7B%22id%22%3A%22testid%22%7D%7D';
|
||||
|
||||
when(connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(mockWSChannel.sink).thenAnswer((_) => MockWSSink());
|
||||
when(mockWSChannel.stream).thenAnswer((_) {
|
||||
return streamController.stream;
|
||||
});
|
||||
final mockWSSink = MockWSSink();
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => mockWSSink);
|
||||
when(() => mockWSSink.close(any(), any())).thenAnswer((_) async => null);
|
||||
when(() => connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
|
||||
ws.connect();
|
||||
await ws.disconnect();
|
||||
streamController.add('{}');
|
||||
|
||||
verify(connectFunc(computedUrl)).called(1);
|
||||
verifyNever(handleFunc(any));
|
||||
verify(() => connectFunc(computedUrl)).called(1);
|
||||
verifyNever(() => handleFunc(any()));
|
||||
|
||||
addTearDown(streamController.close);
|
||||
});
|
||||
|
||||
test('should run correctly health check', () async {
|
||||
final handleFunc = MockFunctions().handleFunc;
|
||||
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
user: User(id: 'testid'),
|
||||
@@ -210,32 +195,28 @@ void main() {
|
||||
handler: handleFunc,
|
||||
connectFunc: connectFunc,
|
||||
);
|
||||
|
||||
final mockWSChannel = MockWSChannel();
|
||||
final mockWSSink = MockWSSink();
|
||||
|
||||
final StreamController<String> streamController =
|
||||
StreamController<String>.broadcast();
|
||||
|
||||
final computedUrl =
|
||||
final streamController = StreamController<String>.broadcast();
|
||||
const computedUrl =
|
||||
'wss://baseurl/connect?test=true&json=%7B%22payload%22%3A%22test%22%2C%22user_details%22%3A%7B%22id%22%3A%22testid%22%7D%7D';
|
||||
|
||||
when(connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(mockWSChannel.stream).thenAnswer((_) {
|
||||
return streamController.stream;
|
||||
});
|
||||
when(mockWSChannel.sink).thenReturn(mockWSSink);
|
||||
when(() => connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => mockWSSink);
|
||||
when(() => mockWSSink.close(any(), any())).thenAnswer((_) async => null);
|
||||
|
||||
final timer = Timer.periodic(
|
||||
Duration(milliseconds: 1000),
|
||||
const Duration(milliseconds: 1000),
|
||||
(_) => streamController.sink.add('{}'),
|
||||
);
|
||||
|
||||
final connect = ws.connect().then((_) {
|
||||
streamController.sink.add('{}');
|
||||
return Future.delayed(Duration(milliseconds: 200));
|
||||
return Future.delayed(const Duration(milliseconds: 200));
|
||||
}).then((value) async {
|
||||
verify(mockWSSink.add("{'type': 'health.check'}")).called(greaterThan(0));
|
||||
verify(() => mockWSSink.add("{'type': 'health.check'}"))
|
||||
.called(greaterThan(0));
|
||||
|
||||
timer.cancel();
|
||||
await streamController.close();
|
||||
@@ -249,9 +230,7 @@ void main() {
|
||||
|
||||
test('should run correctly reconnection check', () async {
|
||||
final handleFunc = MockFunctions().handleFunc;
|
||||
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
Logger.root.level = Level.ALL;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
@@ -262,34 +241,29 @@ void main() {
|
||||
handler: handleFunc,
|
||||
connectFunc: connectFunc,
|
||||
reconnectionMonitorTimeout: 1,
|
||||
reconnectionMonitorInterval: 1,
|
||||
);
|
||||
|
||||
final mockWSChannel = MockWSChannel();
|
||||
final mockWSSink = MockWSSink();
|
||||
|
||||
StreamController<String> streamController =
|
||||
StreamController<String>.broadcast();
|
||||
|
||||
final computedUrl =
|
||||
var streamController = StreamController<String>.broadcast();
|
||||
const computedUrl =
|
||||
'wss://baseurl/connect?test=true&json=%7B%22payload%22%3A%22test%22%2C%22user_details%22%3A%7B%22id%22%3A%22testid%22%7D%7D';
|
||||
|
||||
when(connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(mockWSChannel.stream).thenAnswer((_) {
|
||||
return streamController.stream;
|
||||
});
|
||||
when(mockWSChannel.sink).thenReturn(mockWSSink);
|
||||
when(() => connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => mockWSSink);
|
||||
when(() => mockWSSink.close(any(), any())).thenAnswer((_) async => null);
|
||||
|
||||
final connect = ws.connect().then((_) {
|
||||
streamController.sink.add('{}');
|
||||
streamController.close();
|
||||
streamController = StreamController<String>.broadcast();
|
||||
streamController.sink.add('{}');
|
||||
return Future.delayed(Duration(milliseconds: 200));
|
||||
return Future.delayed(const Duration(milliseconds: 200));
|
||||
}).then((value) async {
|
||||
verify(mockWSSink.add("{'type': 'health.check'}")).called(greaterThan(0));
|
||||
verify(() => mockWSSink.add("{'type': 'health.check'}"))
|
||||
.called(greaterThan(0));
|
||||
|
||||
verify(connectFunc(computedUrl)).called(2);
|
||||
verify(() => connectFunc(computedUrl)).called(2);
|
||||
|
||||
await streamController.close();
|
||||
return mockWSSink.close();
|
||||
@@ -302,9 +276,7 @@ void main() {
|
||||
|
||||
test('should close correctly the controller', () async {
|
||||
final handleFunc = MockFunctions().handleFunc;
|
||||
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
user: User(id: 'testid'),
|
||||
@@ -314,28 +286,23 @@ void main() {
|
||||
handler: handleFunc,
|
||||
connectFunc: connectFunc,
|
||||
);
|
||||
|
||||
final mockWSChannel = MockWSChannel();
|
||||
final mockWSSink = MockWSSink();
|
||||
|
||||
final StreamController<String> streamController =
|
||||
StreamController<String>.broadcast();
|
||||
|
||||
final computedUrl =
|
||||
final streamController = StreamController<String>.broadcast();
|
||||
const computedUrl =
|
||||
'wss://baseurl/connect?test=true&json=%7B%22payload%22%3A%22test%22%2C%22user_details%22%3A%7B%22id%22%3A%22testid%22%7D%7D';
|
||||
|
||||
when(connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(mockWSChannel.stream).thenAnswer((_) {
|
||||
return streamController.stream;
|
||||
});
|
||||
when(mockWSChannel.sink).thenReturn(mockWSSink);
|
||||
when(() => connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => mockWSSink);
|
||||
when(() => mockWSSink.close(any(), any())).thenAnswer((_) async => null);
|
||||
|
||||
final connect = ws.connect().then((_) {
|
||||
streamController.sink.add('{}');
|
||||
return Future.delayed(Duration(milliseconds: 200));
|
||||
return Future.delayed(const Duration(milliseconds: 200));
|
||||
}).then((value) async {
|
||||
await ws.disconnect();
|
||||
verify(mockWSSink.close()).called(greaterThan(0));
|
||||
verify(mockWSSink.close).called(greaterThan(0));
|
||||
|
||||
await streamController.close();
|
||||
await mockWSSink.close();
|
||||
@@ -347,42 +314,35 @@ void main() {
|
||||
});
|
||||
|
||||
test('should throw an error', () async {
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
user: User(id: 'testid'),
|
||||
logger: Logger('ws'),
|
||||
connectParams: {'test': 'true'},
|
||||
connectPayload: {'payload': 'test'},
|
||||
handler: (e) {
|
||||
print(e);
|
||||
},
|
||||
handler: print,
|
||||
connectFunc: connectFunc,
|
||||
);
|
||||
|
||||
final mockWSChannel = MockWSChannel();
|
||||
|
||||
final streamController = StreamController<String>.broadcast();
|
||||
|
||||
final computedUrl =
|
||||
const computedUrl =
|
||||
'wss://baseurl/connect?test=true&json=%7B%22payload%22%3A%22test%22%2C%22user_details%22%3A%7B%22id%22%3A%22testid%22%7D%7D';
|
||||
|
||||
when(connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(mockWSChannel.sink).thenAnswer((_) => MockWSSink());
|
||||
when(mockWSChannel.stream).thenAnswer((_) {
|
||||
return streamController.stream;
|
||||
});
|
||||
when(() => connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => MockWSSink());
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
|
||||
Future.delayed(
|
||||
Duration(milliseconds: 1000),
|
||||
const Duration(milliseconds: 1000),
|
||||
() => streamController.sink.addError('test error'),
|
||||
);
|
||||
|
||||
try {
|
||||
expect(await ws.connect(), throwsA(isA<String>()));
|
||||
} catch (e) {
|
||||
verify(connectFunc(computedUrl)).called(greaterThanOrEqualTo(1));
|
||||
verify(() => connectFunc(computedUrl)).called(greaterThanOrEqualTo(1));
|
||||
streamController.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,8 @@ import 'package:stream_chat/src/models/action.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/action', () {
|
||||
const jsonExample = r'''{
|
||||
const jsonExample = '''
|
||||
{
|
||||
"name": "name",
|
||||
"style": "style",
|
||||
"text": "text",
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import 'package:stream_chat/src/models/attachment.dart';
|
||||
import 'package:stream_chat/src/models/action.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:stream_chat/src/models/action.dart';
|
||||
import 'package:stream_chat/src/models/attachment.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/attachment', () {
|
||||
const jsonExample = r'''{
|
||||
const jsonExample = '''
|
||||
{
|
||||
"type": "giphy",
|
||||
"title": "awesome",
|
||||
"title_link": "https://giphy.com/gifs/nrkp3-dance-happy-3o7TKnCdBx5cMg0qti",
|
||||
@@ -38,22 +39,27 @@ void main() {
|
||||
|
||||
test('should parse json correctly', () {
|
||||
final attachment = Attachment.fromJson(json.decode(jsonExample));
|
||||
expect(attachment.type, "giphy");
|
||||
expect(attachment.title, "awesome");
|
||||
expect(attachment.titleLink,
|
||||
"https://giphy.com/gifs/nrkp3-dance-happy-3o7TKnCdBx5cMg0qti");
|
||||
expect(attachment.thumbUrl,
|
||||
"https://media0.giphy.com/media/3o7TKnCdBx5cMg0qti/giphy.gif");
|
||||
expect(attachment.type, 'giphy');
|
||||
expect(attachment.title, 'awesome');
|
||||
expect(
|
||||
attachment.titleLink,
|
||||
'https://giphy.com/gifs/nrkp3-dance-happy-3o7TKnCdBx5cMg0qti',
|
||||
);
|
||||
expect(
|
||||
attachment.thumbUrl,
|
||||
'https://media0.giphy.com/media/3o7TKnCdBx5cMg0qti/giphy.gif',
|
||||
);
|
||||
expect(attachment.actions, hasLength(3));
|
||||
expect(attachment.actions[0], isA<Action>());
|
||||
});
|
||||
|
||||
test('should serialize to json correctly', () {
|
||||
final channel = Attachment(
|
||||
type: "image",
|
||||
title: "soo",
|
||||
titleLink:
|
||||
"https://giphy.com/gifs/nrkp3-dance-happy-3o7TKnCdBx5cMg0qti");
|
||||
type: 'image',
|
||||
title: 'soo',
|
||||
titleLink:
|
||||
'https://giphy.com/gifs/nrkp3-dance-happy-3o7TKnCdBx5cMg0qti',
|
||||
);
|
||||
|
||||
expect(
|
||||
channel.toJson(),
|
||||
@@ -61,7 +67,8 @@ void main() {
|
||||
'type': 'image',
|
||||
'title': 'soo',
|
||||
'title_link':
|
||||
'https://giphy.com/gifs/nrkp3-dance-happy-3o7TKnCdBx5cMg0qti'
|
||||
'https://giphy.com/gifs/nrkp3-dance-happy-3o7TKnCdBx5cMg0qti',
|
||||
'actions': [],
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/models/channel_config.dart';
|
||||
import 'package:stream_chat/src/models/channel_state.dart';
|
||||
import 'package:stream_chat/src/models/command.dart';
|
||||
import 'package:stream_chat/src/models/message.dart';
|
||||
import 'package:stream_chat/src/models/user.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/channel_state', () {
|
||||
const jsonExample = r'''{
|
||||
const jsonExample = '''
|
||||
{
|
||||
"channel": {
|
||||
"id": "dev",
|
||||
"type": "team",
|
||||
@@ -844,37 +845,41 @@ 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,
|
||||
DateTime.parse("2020-01-30T13:43:41.062362Z"));
|
||||
expect(channelState.channel.createdAt,
|
||||
DateTime.parse("2019-04-03T18:43:33.213373Z"));
|
||||
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.extraData['image'],
|
||||
"https://cdn.chrisshort.net/testing-certificate-chains-in-go/GOPHER_MIC_DROP.png");
|
||||
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,
|
||||
DateTime.parse('2019-04-03T18:43:33.213373Z'));
|
||||
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?.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].createdAt,
|
||||
DateTime.parse("2020-01-29T03:23:02.843948Z"));
|
||||
expect(
|
||||
channelState.messages[0].createdAt,
|
||||
DateTime.parse('2020-01-29T03:23:02.843948Z'),
|
||||
);
|
||||
expect(channelState.messages[0].user, isA<User>());
|
||||
expect(channelState.watcherCount, 5);
|
||||
});
|
||||
|
||||
test('should serialize to json correctly', () {
|
||||
const toJsonExample = r'''
|
||||
const toJsonExample = '''
|
||||
{
|
||||
"channel": {
|
||||
"id": "dev",
|
||||
@@ -884,8 +889,8 @@ void main() {
|
||||
"image": "https://cdn.chrisshort.net/testing-certificate-chains-in-go/GOPHER_MIC_DROP.png",
|
||||
"example": 1
|
||||
},
|
||||
"watchers": null,
|
||||
"read": null,
|
||||
"watchers": [],
|
||||
"read": [],
|
||||
"messages": [
|
||||
{
|
||||
"id": "dry-meadow-0-2b73cc8b-cd86-4a01-8d40-bd82ad07a030",
|
||||
@@ -897,7 +902,7 @@ void main() {
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
@@ -914,7 +919,7 @@ void main() {
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
@@ -924,7 +929,7 @@ void main() {
|
||||
{
|
||||
"id": "dry-meadow-0-53e6299f-9b97-4a9c-a27e-7e2dde49b7e0",
|
||||
"text": "test message",
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
@@ -947,7 +952,7 @@ void main() {
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
@@ -959,7 +964,7 @@ void main() {
|
||||
"id": "dry-meadow-0-64d7970f-ede8-4b31-9738-1bc1756d2bfe",
|
||||
"text": "test",
|
||||
"attachments": [],
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
@@ -977,7 +982,7 @@ void main() {
|
||||
"text": "hi",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
@@ -995,7 +1000,7 @@ void main() {
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
@@ -1018,7 +1023,7 @@ void main() {
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
@@ -1036,7 +1041,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1048,7 +1053,7 @@ void main() {
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
@@ -1066,7 +1071,7 @@ void main() {
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
@@ -1085,7 +1090,7 @@ void main() {
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
@@ -1095,7 +1100,7 @@ void main() {
|
||||
"id": "icy-recipe-7-935c396e-ddf8-4a9a-951c-0a12fa5bf055",
|
||||
"text": "what are you doing?",
|
||||
"attachments": [],
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
@@ -1113,7 +1118,7 @@ void main() {
|
||||
"text": "👍",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
@@ -1129,7 +1134,7 @@ void main() {
|
||||
"id": "snowy-credit-3-3e0c1a0d-d22f-42ee-b2a1-f9f49477bf21",
|
||||
"text": "sdasas",
|
||||
"attachments": [],
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
@@ -1150,7 +1155,7 @@ void main() {
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
@@ -1163,7 +1168,7 @@ void main() {
|
||||
"id": "snowy-credit-3-cfaf0b46-1daa-49c5-947c-b16d6697487d",
|
||||
"text": "nhisagdhsadz",
|
||||
"attachments": [],
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
@@ -1182,7 +1187,7 @@ void main() {
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
@@ -1199,7 +1204,7 @@ void main() {
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
@@ -1207,7 +1212,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1224,7 +1229,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1241,7 +1246,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1258,7 +1263,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1275,7 +1280,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1292,7 +1297,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1309,7 +1314,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
}
|
||||
@@ -1325,10 +1330,10 @@ void main() {
|
||||
members: [],
|
||||
messages:
|
||||
(j['messages'] as List).map((m) => Message.fromJson(m)).toList(),
|
||||
read: null,
|
||||
read: [],
|
||||
watcherCount: 5,
|
||||
pinnedMessages: [],
|
||||
watchers: null,
|
||||
watchers: [],
|
||||
);
|
||||
|
||||
expect(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/models/channel_model.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/channel', () {
|
||||
@@ -9,7 +9,7 @@ void main() {
|
||||
{
|
||||
"id": "test",
|
||||
"type": "livestream",
|
||||
"cid": "test:livestream",
|
||||
"cid": "livestream:test",
|
||||
"cats": true,
|
||||
"fruit": ["bananas", "apples"]
|
||||
}
|
||||
@@ -17,34 +17,33 @@ void main() {
|
||||
|
||||
test('should parse json correctly', () {
|
||||
final channel = ChannelModel.fromJson(json.decode(jsonExample));
|
||||
expect(channel.id, equals("test"));
|
||||
expect(channel.type, equals("livestream"));
|
||||
expect(channel.cid, equals("test:livestream"));
|
||||
expect(channel.extraData["cats"], equals(true));
|
||||
expect(channel.extraData["fruit"], equals(["bananas", "apples"]));
|
||||
expect(channel.id, equals('test'));
|
||||
expect(channel.type, equals('livestream'));
|
||||
expect(channel.cid, equals('livestream:test'));
|
||||
expect(channel.extraData['cats'], equals(true));
|
||||
expect(channel.extraData['fruit'], equals(['bananas', 'apples']));
|
||||
});
|
||||
|
||||
test('should serialize to json correctly', () {
|
||||
final channel = ChannelModel(
|
||||
type: "type",
|
||||
id: "id",
|
||||
cid: "a:a",
|
||||
extraData: {"name": "cool"},
|
||||
type: 'type',
|
||||
id: 'id',
|
||||
cid: 'a:a',
|
||||
extraData: {'name': 'cool'},
|
||||
);
|
||||
|
||||
expect(
|
||||
channel.toJson(),
|
||||
{'id': 'id', 'type': 'type', 'name': 'cool'},
|
||||
{'id': 'id', 'type': 'type', 'frozen': false, 'name': 'cool'},
|
||||
);
|
||||
});
|
||||
|
||||
test('should serialize to json correctly when frozen is provided', () {
|
||||
final channel = ChannelModel(
|
||||
type: "type",
|
||||
id: "id",
|
||||
cid: "a:a",
|
||||
extraData: {"name": "cool"},
|
||||
frozen: false,
|
||||
type: 'type',
|
||||
id: 'id',
|
||||
cid: 'a:a',
|
||||
extraData: {'name': 'cool'},
|
||||
);
|
||||
|
||||
expect(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:stream_chat/src/models/command.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:stream_chat/src/models/command.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
@@ -30,9 +30,9 @@ void main() {
|
||||
expect(
|
||||
command.toJson(),
|
||||
{
|
||||
"name": "giphy",
|
||||
"description": "Post a random gif to the channel",
|
||||
"args": "[text]",
|
||||
'name': 'giphy',
|
||||
'description': 'Post a random gif to the channel',
|
||||
'args': '[text]',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -5,7 +5,8 @@ import 'package:stream_chat/src/models/device.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/device', () {
|
||||
const jsonExample = r'''{
|
||||
const jsonExample = '''
|
||||
{
|
||||
"id": "device-id",
|
||||
"push_provider": "push-provider"
|
||||
}''';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/models/event.dart';
|
||||
import 'package:stream_chat/src/models/own_user.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/event', () {
|
||||
@@ -47,6 +47,7 @@ void main() {
|
||||
expect(event.createdAt, isA<DateTime>());
|
||||
expect(event.me, isA<OwnUser>());
|
||||
expect(event.user, isA<User>());
|
||||
expect(event.isLocal, false);
|
||||
});
|
||||
|
||||
test('should serialize to json correctly', () {
|
||||
@@ -55,7 +56,7 @@ void main() {
|
||||
type: 'type',
|
||||
cid: 'cid',
|
||||
connectionId: 'connectionId',
|
||||
createdAt: DateTime.parse("2020-01-29T03:22:47.63613Z"),
|
||||
createdAt: DateTime.parse('2020-01-29T03:22:47.63613Z'),
|
||||
me: OwnUser(id: 'id2'),
|
||||
totalUnreadCount: 1,
|
||||
unreadChannels: 1,
|
||||
@@ -77,11 +78,11 @@ void main() {
|
||||
'total_unread_count': 1,
|
||||
'unread_channels': 1,
|
||||
'online': true,
|
||||
'is_local': true,
|
||||
'member': null,
|
||||
'channel_id': null,
|
||||
'channel_type': null,
|
||||
'parent_id': null,
|
||||
'is_local': true,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/models/filter.dart';
|
||||
|
||||
void main() {
|
||||
group('operators', () {
|
||||
test('equal', () {
|
||||
const key = 'testKey';
|
||||
const value = 'testValue';
|
||||
final filter = Filter.equal(key, value);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, value);
|
||||
expect(filter.operator, FilterOperator.equal.rawValue);
|
||||
});
|
||||
|
||||
test('notEqual', () {
|
||||
const key = 'testKey';
|
||||
const value = 'testValue';
|
||||
final filter = Filter.notEqual(key, value);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, value);
|
||||
expect(filter.operator, FilterOperator.notEqual.rawValue);
|
||||
});
|
||||
|
||||
test('greater', () {
|
||||
const key = 'testKey';
|
||||
const value = 'testValue';
|
||||
final filter = Filter.greater(key, value);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, value);
|
||||
expect(filter.operator, FilterOperator.greater.rawValue);
|
||||
});
|
||||
|
||||
test('greaterOrEqual', () {
|
||||
const key = 'testKey';
|
||||
const value = 'testValue';
|
||||
final filter = Filter.greaterOrEqual(key, value);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, value);
|
||||
expect(filter.operator, FilterOperator.greaterOrEqual.rawValue);
|
||||
});
|
||||
|
||||
test('less', () {
|
||||
const key = 'testKey';
|
||||
const value = 'testValue';
|
||||
final filter = Filter.less(key, value);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, value);
|
||||
expect(filter.operator, FilterOperator.less.rawValue);
|
||||
});
|
||||
|
||||
test('lessOrEqual', () {
|
||||
const key = 'testKey';
|
||||
const value = 'testValue';
|
||||
final filter = Filter.lessOrEqual(key, value);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, value);
|
||||
expect(filter.operator, FilterOperator.lessOrEqual.rawValue);
|
||||
});
|
||||
|
||||
test('in', () {
|
||||
const key = 'testKey';
|
||||
const values = ['testValue'];
|
||||
final filter = Filter.in_(key, values);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, values);
|
||||
expect(filter.operator, FilterOperator.in_.rawValue);
|
||||
});
|
||||
|
||||
test('in', () {
|
||||
const key = 'testKey';
|
||||
const values = ['testValue'];
|
||||
final filter = Filter.in_(key, values);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, values);
|
||||
expect(filter.operator, FilterOperator.in_.rawValue);
|
||||
});
|
||||
|
||||
test('notIn', () {
|
||||
const key = 'testKey';
|
||||
const values = ['testValue'];
|
||||
final filter = Filter.notIn(key, values);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, values);
|
||||
expect(filter.operator, FilterOperator.notIn.rawValue);
|
||||
});
|
||||
|
||||
test('query', () {
|
||||
const key = 'testKey';
|
||||
const value = 'testQuery';
|
||||
final filter = Filter.query(key, value);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, value);
|
||||
expect(filter.operator, FilterOperator.query.rawValue);
|
||||
});
|
||||
|
||||
test('autoComplete', () {
|
||||
const key = 'testKey';
|
||||
const value = 'testQuery';
|
||||
final filter = Filter.autoComplete(key, value);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, value);
|
||||
expect(filter.operator, FilterOperator.autoComplete.rawValue);
|
||||
});
|
||||
|
||||
test('exists', () {
|
||||
const key = 'testKey';
|
||||
final filter = Filter.exists(key);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, isTrue);
|
||||
expect(filter.operator, FilterOperator.exists.rawValue);
|
||||
});
|
||||
|
||||
test('notExists', () {
|
||||
const key = 'testKey';
|
||||
final filter = Filter.exists(key, exists: false);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, isFalse);
|
||||
expect(filter.operator, FilterOperator.exists.rawValue);
|
||||
});
|
||||
|
||||
test('custom', () {
|
||||
const key = 'testKey';
|
||||
const value = 'testValue';
|
||||
const operator = '\$customOperator';
|
||||
const filter = Filter.custom(operator: operator, key: key, value: value);
|
||||
expect(filter.key, key);
|
||||
expect(filter.value, value);
|
||||
expect(filter.operator, operator);
|
||||
});
|
||||
|
||||
group('groupedOperator', () {
|
||||
final filter1 = Filter.equal('testKey', 'testValue');
|
||||
final filter2 = Filter.in_('testKey', const ['testValue']);
|
||||
final filters = [filter1, filter2];
|
||||
|
||||
test('and', () {
|
||||
final filter = Filter.and(filters);
|
||||
expect(filter.key, isNull);
|
||||
expect(filter.value, filters);
|
||||
expect(filter.operator, FilterOperator.and.rawValue);
|
||||
});
|
||||
|
||||
test('or', () {
|
||||
final filter = Filter.or(filters);
|
||||
expect(filter.key, isNull);
|
||||
expect(filter.value, filters);
|
||||
expect(filter.operator, FilterOperator.or.rawValue);
|
||||
});
|
||||
|
||||
test('nor', () {
|
||||
final filter = Filter.nor(filters);
|
||||
expect(filter.key, isNull);
|
||||
expect(filter.value, filters);
|
||||
expect(filter.operator, FilterOperator.nor.rawValue);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('encoding', () {
|
||||
group('nonGroupedFilter', () {
|
||||
test('simpleValue', () {
|
||||
const key = 'testKey';
|
||||
const value = 'testValue';
|
||||
final filter = Filter.equal(key, value);
|
||||
final encoded = json.encode(filter);
|
||||
expect(
|
||||
encoded,
|
||||
'{"$key":{"${FilterOperator.equal.rawValue}":${json.encode(value)}}}',
|
||||
);
|
||||
});
|
||||
test('listValue', () {
|
||||
const key = 'testKey';
|
||||
const values = ['testValue'];
|
||||
final filter = Filter.in_(key, values);
|
||||
final encoded = json.encode(filter);
|
||||
expect(
|
||||
encoded,
|
||||
'{"$key":{"${FilterOperator.in_.rawValue}":${json.encode(values)}}}',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('groupedFilter', () {
|
||||
final filter1 = Filter.equal('testKey', 'testValue');
|
||||
final filter2 = Filter.in_('testKey', const ['testValue']);
|
||||
final filters = [filter1, filter2];
|
||||
|
||||
final filter = Filter.and(filters);
|
||||
final encoded = json.encode(filter);
|
||||
expect(
|
||||
encoded,
|
||||
'{"${FilterOperator.and.rawValue}":${json.encode(filters)}}',
|
||||
);
|
||||
});
|
||||
|
||||
group('equality', () {
|
||||
test('simpleFilter', () {
|
||||
final filter1 = Filter.equal('testKey', 'testValue');
|
||||
final filter2 = Filter.equal('testKey', 'testValue');
|
||||
expect(filter1, filter2);
|
||||
});
|
||||
|
||||
test('groupedFilter', () {
|
||||
final filter1 = Filter.and([Filter.equal('testKey', 'testValue')]);
|
||||
final filter2 = Filter.and([Filter.equal('testKey', 'testValue')]);
|
||||
expect(filter1, filter2);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -28,8 +28,8 @@ void main() {
|
||||
final member = Member.fromJson(json.decode(jsonExample));
|
||||
expect(member.user, isA<User>());
|
||||
expect(member.role, 'member');
|
||||
expect(member.createdAt, DateTime.parse("2020-01-28T22:17:30.95443Z"));
|
||||
expect(member.updatedAt, DateTime.parse("2020-01-28T22:17:30.95443Z"));
|
||||
expect(member.createdAt, DateTime.parse('2020-01-28T22:17:30.95443Z'));
|
||||
expect(member.updatedAt, DateTime.parse('2020-01-28T22:17:30.95443Z'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/models/attachment.dart';
|
||||
import 'package:stream_chat/src/models/message.dart';
|
||||
import 'package:stream_chat/src/models/reaction.dart';
|
||||
import 'package:stream_chat/src/models/user.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/message', () {
|
||||
const jsonExample = r'''{
|
||||
const jsonExample = r'''
|
||||
{
|
||||
"id": "4637f7e4-a06b-42db-ba5a-8d8270dd926f",
|
||||
"text": "https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA",
|
||||
"type": "regular",
|
||||
@@ -76,10 +77,10 @@ void main() {
|
||||
|
||||
test('should parse json correctly', () {
|
||||
final message = Message.fromJson(json.decode(jsonExample));
|
||||
expect(message.id, "4637f7e4-a06b-42db-ba5a-8d8270dd926f");
|
||||
expect(message.id, '4637f7e4-a06b-42db-ba5a-8d8270dd926f');
|
||||
expect(message.text,
|
||||
"https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA");
|
||||
expect(message.type, "regular");
|
||||
'https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA');
|
||||
expect(message.type, 'regular');
|
||||
expect(message.user, isA<User>());
|
||||
expect(message.silent, isA<bool>());
|
||||
expect(message.attachments, isA<List<Attachment>>());
|
||||
@@ -87,8 +88,8 @@ void main() {
|
||||
expect(message.ownReactions, isA<List<Reaction>>());
|
||||
expect(message.reactionCounts, {'love': 1});
|
||||
expect(message.reactionScores, {'love': 1});
|
||||
expect(message.createdAt, DateTime.parse("2020-01-28T22:17:31.107978Z"));
|
||||
expect(message.updatedAt, DateTime.parse("2020-01-28T22:17:31.130506Z"));
|
||||
expect(message.createdAt, DateTime.parse('2020-01-28T22:17:31.107978Z'));
|
||||
expect(message.updatedAt, DateTime.parse('2020-01-28T22:17:31.130506Z'));
|
||||
expect(message.mentionedUsers, isA<List<User>>());
|
||||
expect(message.pinned, false);
|
||||
expect(message.pinnedAt, null);
|
||||
@@ -98,43 +99,41 @@ void main() {
|
||||
|
||||
test('should serialize to json correctly', () {
|
||||
final message = Message(
|
||||
id: "4637f7e4-a06b-42db-ba5a-8d8270dd926f",
|
||||
id: '4637f7e4-a06b-42db-ba5a-8d8270dd926f',
|
||||
text:
|
||||
"https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA",
|
||||
silent: false,
|
||||
'https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA',
|
||||
attachments: [
|
||||
Attachment.fromJson({
|
||||
"type": "video",
|
||||
"author_name": "GIPHY",
|
||||
"title": "The Lion King Disney GIF - Find \u0026 Share on GIPHY",
|
||||
"title_link":
|
||||
"https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.gif",
|
||||
"text":
|
||||
"Discover \u0026 share this Lion King Live Action GIF with everyone you know. GIPHY is how you search, share, discover, and create GIFs.",
|
||||
"image_url":
|
||||
"https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.gif",
|
||||
"thumb_url":
|
||||
"https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.gif",
|
||||
"asset_url":
|
||||
"https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.mp4",
|
||||
"og_scrape_url":
|
||||
"https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA"
|
||||
Attachment.fromJson(const {
|
||||
'type': 'video',
|
||||
'author_name': 'GIPHY',
|
||||
'title': 'The Lion King Disney GIF - Find \u0026 Share on GIPHY',
|
||||
'title_link':
|
||||
'https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.gif',
|
||||
'text':
|
||||
'''Discover \u0026 share this Lion King Live Action GIF with everyone you know. GIPHY is how you search, share, discover, and create GIFs.''',
|
||||
'image_url':
|
||||
'https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.gif',
|
||||
'thumb_url':
|
||||
'https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.gif',
|
||||
'asset_url':
|
||||
'https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.mp4',
|
||||
'og_scrape_url':
|
||||
'https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA'
|
||||
})
|
||||
],
|
||||
showInChannel: true,
|
||||
parentId: 'parentId',
|
||||
extraData: {'hey': 'test'},
|
||||
status: MessageSendingStatus.sent,
|
||||
extraData: const {'hey': 'test'},
|
||||
);
|
||||
|
||||
expect(
|
||||
message.toJson(),
|
||||
json.decode(r'''
|
||||
json.decode('''
|
||||
{
|
||||
"id": "4637f7e4-a06b-42db-ba5a-8d8270dd926f",
|
||||
"text": "https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA",
|
||||
"silent": false,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"attachments": [
|
||||
{
|
||||
"type": "video",
|
||||
@@ -145,10 +144,11 @@ void main() {
|
||||
"og_scrape_url": "https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA",
|
||||
"image_url": "https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.gif",
|
||||
"author_name": "GIPHY",
|
||||
"asset_url": "https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.mp4"
|
||||
"asset_url": "https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.mp4",
|
||||
"actions": []
|
||||
}
|
||||
],
|
||||
"mentioned_users": null,
|
||||
"mentioned_users": [],
|
||||
"parent_id": "parentId",
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/models/reaction.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:stream_chat/src/models/reaction.dart';
|
||||
import 'package:stream_chat/src/models/user.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/reaction', () {
|
||||
@@ -30,13 +30,13 @@ void main() {
|
||||
test('should parse json correctly', () {
|
||||
final reaction = Reaction.fromJson(json.decode(jsonExample));
|
||||
expect(reaction.messageId, '76cd8c82-b557-4e48-9d12-87995d3a0e04');
|
||||
expect(reaction.createdAt, DateTime.parse("2020-01-28T22:17:31.108742Z"));
|
||||
expect(reaction.createdAt, DateTime.parse('2020-01-28T22:17:31.108742Z'));
|
||||
expect(reaction.type, 'wow');
|
||||
expect(
|
||||
reaction.user.toJson(),
|
||||
User.init("2de0297c-f3f2-489d-b930-ef77342edccf", extraData: {
|
||||
"image": "https://randomuser.me/api/portraits/women/45.jpg",
|
||||
"name": "Daisy Morgan"
|
||||
reaction.user?.toJson(),
|
||||
User(id: '2de0297c-f3f2-489d-b930-ef77342edccf', extraData: {
|
||||
'image': 'https://randomuser.me/api/portraits/women/45.jpg',
|
||||
'name': 'Daisy Morgan'
|
||||
}).toJson(),
|
||||
);
|
||||
expect(reaction.score, 1);
|
||||
@@ -47,13 +47,13 @@ void main() {
|
||||
test('should serialize to json correctly', () {
|
||||
final reaction = Reaction(
|
||||
messageId: '76cd8c82-b557-4e48-9d12-87995d3a0e04',
|
||||
createdAt: DateTime.parse("2020-01-28T22:17:31.108742Z"),
|
||||
createdAt: DateTime.parse('2020-01-28T22:17:31.108742Z'),
|
||||
type: 'wow',
|
||||
user: User.init("2de0297c-f3f2-489d-b930-ef77342edccf", extraData: {
|
||||
"image": "https://randomuser.me/api/portraits/women/45.jpg",
|
||||
"name": "Daisy Morgan"
|
||||
user: User(id: '2de0297c-f3f2-489d-b930-ef77342edccf', extraData: {
|
||||
'image': 'https://randomuser.me/api/portraits/women/45.jpg',
|
||||
'name': 'Daisy Morgan'
|
||||
}),
|
||||
userId: "2de0297c-f3f2-489d-b930-ef77342edccf",
|
||||
userId: '2de0297c-f3f2-489d-b930-ef77342edccf',
|
||||
extraData: {'bananas': 'yes'},
|
||||
score: 1,
|
||||
);
|
||||
@@ -61,10 +61,10 @@ void main() {
|
||||
expect(
|
||||
reaction.toJson(),
|
||||
{
|
||||
"message_id": "76cd8c82-b557-4e48-9d12-87995d3a0e04",
|
||||
"type": "wow",
|
||||
"score": 1,
|
||||
"bananas": 'yes',
|
||||
'message_id': '76cd8c82-b557-4e48-9d12-87995d3a0e04',
|
||||
'type': 'wow',
|
||||
'score': 1,
|
||||
'bananas': 'yes',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -26,13 +26,13 @@ void main() {
|
||||
test('should serialize to json correctly', () {
|
||||
final read = Read(
|
||||
lastRead: DateTime.parse('2020-01-28T22:17:30.966485504Z'),
|
||||
user: User.init('bbb19d9a-ee50-45bc-84e5-0584e79d0c9e'),
|
||||
user: User(id: 'bbb19d9a-ee50-45bc-84e5-0584e79d0c9e'),
|
||||
unreadMessages: 10,
|
||||
);
|
||||
|
||||
expect(read.toJson(), {
|
||||
"user": {"id": "bbb19d9a-ee50-45bc-84e5-0584e79d0c9e"},
|
||||
"last_read": "2020-01-28T22:17:30.966485Z",
|
||||
'user': {'id': 'bbb19d9a-ee50-45bc-84e5-0584e79d0c9e'},
|
||||
'last_read': '2020-01-28T22:17:30.966485Z',
|
||||
'unread_messages': 10,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -49,12 +49,12 @@ void main() {
|
||||
});
|
||||
|
||||
test('should return null', () {
|
||||
final result = Serialization.moveToExtraDataFromRoot(null, [
|
||||
final result = Serialization.moveToExtraDataFromRoot({}, [
|
||||
'prop1',
|
||||
'prop2',
|
||||
]);
|
||||
|
||||
expect(result, null);
|
||||
expect(result, {'extra_data': {}});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/models/user.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/user', () {
|
||||
const jsonExample = '''
|
||||
{
|
||||
"id": "bbb19d9a-ee50-45bc-84e5-0584e79d0c9e"
|
||||
"id": "bbb19d9a-ee50-45bc-84e5-0584e79d0c9e",
|
||||
"role": "test-role"
|
||||
}
|
||||
''';
|
||||
|
||||
@@ -17,11 +18,13 @@ void main() {
|
||||
});
|
||||
|
||||
test('should serialize to json correctly', () {
|
||||
final user =
|
||||
User(id: 'bbb19d9a-ee50-45bc-84e5-0584e79d0c9e', role: "abc");
|
||||
final user = User(
|
||||
id: 'bbb19d9a-ee50-45bc-84e5-0584e79d0c9e',
|
||||
role: 'abc',
|
||||
);
|
||||
|
||||
expect(user.toJson(), {
|
||||
'id': "bbb19d9a-ee50-45bc-84e5-0584e79d0c9e",
|
||||
'id': 'bbb19d9a-ee50-45bc-84e5-0584e79d0c9e',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/version.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void prepareTest() {
|
||||
// https://github.com/flutter/flutter/issues/20907
|
||||
@@ -14,11 +13,12 @@ void prepareTest() {
|
||||
void main() {
|
||||
prepareTest();
|
||||
test('stream chat version matches pubspec', () {
|
||||
final String pubspecPath = '${Directory.current.path}/pubspec.yaml';
|
||||
final String pubspec = File(pubspecPath).readAsStringSync();
|
||||
final RegExp regex = RegExp('version:\s*(.*)');
|
||||
final RegExpMatch match = regex.firstMatch(pubspec);
|
||||
final pubspecPath = '${Directory.current.path}/pubspec.yaml';
|
||||
final pubspec = File(pubspecPath).readAsStringSync();
|
||||
// ignore: unnecessary_string_escapes
|
||||
final regex = RegExp('version:\s*(.*)');
|
||||
final match = regex.firstMatch(pubspec);
|
||||
expect(match, isNotNull);
|
||||
expect(PACKAGE_VERSION, match.group(1).trim());
|
||||
expect(PACKAGE_VERSION, match?.group(1)?.trim());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
## 2.0.0-nullsafety.0
|
||||
|
||||
- Migrate this package to null safety
|
||||
- Updated `stream_chat_core` dependency
|
||||
|
||||
## 1.5.3
|
||||
|
||||
- Updated `stream_chat_core` dependency
|
||||
|
||||
@@ -6,6 +6,7 @@ analyzer:
|
||||
exclude:
|
||||
- lib/**/*.g.dart
|
||||
- example/**
|
||||
- lib/src/emoji
|
||||
|
||||
linter:
|
||||
rules:
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/Users/salvatoregiordano/fvm/versions/beta
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"flutterSdkVersion": "beta"
|
||||
}
|
||||
@@ -61,8 +61,8 @@ class MyApp extends StatelessWidget {
|
||||
themeMode: ThemeMode.system,
|
||||
builder: (context, widget) {
|
||||
return StreamChat(
|
||||
child: widget,
|
||||
client: client,
|
||||
child: widget,
|
||||
);
|
||||
},
|
||||
home: StreamChannel(
|
||||
@@ -80,7 +80,7 @@ class MyApp extends StatelessWidget {
|
||||
class ChannelPage extends StatelessWidget {
|
||||
/// Creates the page that shows the list of messages
|
||||
const ChannelPage({
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
||||
@@ -25,8 +25,8 @@ class MyApp extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
builder: (context, child) => StreamChat(
|
||||
child: child,
|
||||
client: client,
|
||||
child: child,
|
||||
),
|
||||
home: SplitView(),
|
||||
);
|
||||
@@ -39,7 +39,7 @@ class SplitView extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _SplitViewState extends State<SplitView> {
|
||||
Channel selectedChannel;
|
||||
Channel? selectedChannel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -47,6 +47,7 @@ class _SplitViewState extends State<SplitView> {
|
||||
direction: Axis.horizontal,
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: ChannelListPage(
|
||||
onTap: (channel) {
|
||||
setState(() {
|
||||
@@ -54,15 +55,15 @@ class _SplitViewState extends State<SplitView> {
|
||||
});
|
||||
},
|
||||
),
|
||||
flex: 1,
|
||||
),
|
||||
Flexible(
|
||||
flex: 2,
|
||||
child: Scaffold(
|
||||
body: selectedChannel != null
|
||||
? StreamChannel(
|
||||
key: ValueKey(selectedChannel.cid),
|
||||
key: ValueKey(selectedChannel!.cid),
|
||||
channel: selectedChannel!,
|
||||
child: ChannelPage(),
|
||||
channel: selectedChannel,
|
||||
)
|
||||
: Center(
|
||||
child: Text(
|
||||
@@ -71,7 +72,6 @@ class _SplitViewState extends State<SplitView> {
|
||||
),
|
||||
),
|
||||
),
|
||||
flex: 2,
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -79,7 +79,7 @@ class _SplitViewState extends State<SplitView> {
|
||||
}
|
||||
|
||||
class ChannelListPage extends StatelessWidget {
|
||||
final void Function(Channel) onTap;
|
||||
final void Function(Channel)? onTap;
|
||||
|
||||
ChannelListPage({this.onTap});
|
||||
|
||||
@@ -90,14 +90,13 @@ class ChannelListPage extends StatelessWidget {
|
||||
child: ChannelListView(
|
||||
onChannelTap: onTap != null
|
||||
? (channel, _) {
|
||||
onTap(channel);
|
||||
onTap!(channel);
|
||||
}
|
||||
: null,
|
||||
filter: {
|
||||
'members': {
|
||||
'\$in': [StreamChat.of(context).user.id],
|
||||
}
|
||||
},
|
||||
filter: Filter.in_(
|
||||
'members',
|
||||
[StreamChat.of(context).user!.id],
|
||||
),
|
||||
sort: [SortOption('last_message_at')],
|
||||
pagination: PaginationParams(
|
||||
limit: 20,
|
||||
@@ -110,7 +109,7 @@ class ChannelListPage extends StatelessWidget {
|
||||
|
||||
class ChannelPage extends StatelessWidget {
|
||||
const ChannelPage({
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
||||
@@ -55,8 +55,8 @@ class MyApp extends StatelessWidget {
|
||||
return MaterialApp(
|
||||
builder: (context, widget) {
|
||||
return StreamChat(
|
||||
child: widget,
|
||||
client: client,
|
||||
child: widget,
|
||||
);
|
||||
},
|
||||
home: StreamChannel(
|
||||
@@ -69,7 +69,7 @@ class MyApp extends StatelessWidget {
|
||||
|
||||
class ChannelPage extends StatelessWidget {
|
||||
const ChannelPage({
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
||||
@@ -56,11 +56,10 @@ class ChannelListPage extends StatelessWidget {
|
||||
return Scaffold(
|
||||
body: ChannelsBloc(
|
||||
child: ChannelListView(
|
||||
filter: {
|
||||
// 'members': {
|
||||
// '\$in': [StreamChat.of(context).user.id],
|
||||
// }
|
||||
},
|
||||
filter: Filter.in_(
|
||||
'members',
|
||||
[StreamChat.of(context).user.id],
|
||||
),
|
||||
sort: [SortOption('last_message_at')],
|
||||
pagination: PaginationParams(
|
||||
limit: 20,
|
||||
@@ -74,7 +73,7 @@ class ChannelListPage extends StatelessWidget {
|
||||
|
||||
class ChannelPage extends StatelessWidget {
|
||||
const ChannelPage({
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// ignore_for_file: public_member_api_docs
|
||||
import 'package:collection/collection.dart' show IterableExtension;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
|
||||
@@ -43,8 +44,8 @@ class MyApp extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
builder: (context, child) => StreamChat(
|
||||
child: child,
|
||||
client: client,
|
||||
child: child,
|
||||
),
|
||||
home: ChannelListPage(),
|
||||
);
|
||||
@@ -57,11 +58,10 @@ class ChannelListPage extends StatelessWidget {
|
||||
return Scaffold(
|
||||
body: ChannelsBloc(
|
||||
child: ChannelListView(
|
||||
filter: {
|
||||
'members': {
|
||||
'\$in': [StreamChat.of(context).user.id],
|
||||
}
|
||||
},
|
||||
filter: Filter.in_(
|
||||
'members',
|
||||
[StreamChat.of(context).user!.id],
|
||||
),
|
||||
channelPreviewBuilder: _channelPreviewBuilder,
|
||||
// sort: [SortOption('last_message_at')],
|
||||
pagination: PaginationParams(
|
||||
@@ -74,13 +74,12 @@ class ChannelListPage extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget _channelPreviewBuilder(BuildContext context, Channel channel) {
|
||||
final lastMessage = channel.state.messages.reversed.firstWhere(
|
||||
final lastMessage = channel.state?.messages.reversed.firstWhereOrNull(
|
||||
(message) => !message.isDeleted,
|
||||
orElse: () => null,
|
||||
);
|
||||
|
||||
final subtitle = (lastMessage == null ? 'nothing yet' : lastMessage.text);
|
||||
final opacity = channel.state.unreadCount > .0 ? 1.0 : 0.5;
|
||||
final subtitle = (lastMessage == null ? 'nothing yet' : lastMessage.text!);
|
||||
final opacity = (channel.state?.unreadCount ?? 0) > 0 ? 1.0 : 0.5;
|
||||
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
@@ -88,8 +87,8 @@ class ChannelListPage extends StatelessWidget {
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => StreamChannel(
|
||||
child: ChannelPage(),
|
||||
channel: channel,
|
||||
child: ChannelPage(),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -99,7 +98,7 @@ class ChannelListPage extends StatelessWidget {
|
||||
),
|
||||
title: ChannelName(
|
||||
textStyle:
|
||||
StreamChatTheme.of(context).channelPreviewTheme.title.copyWith(
|
||||
StreamChatTheme.of(context).channelPreviewTheme.title!.copyWith(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.black
|
||||
@@ -107,10 +106,10 @@ class ChannelListPage extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
subtitle: Text(subtitle),
|
||||
trailing: channel.state.unreadCount > 0
|
||||
trailing: channel.state!.unreadCount! > 0
|
||||
? CircleAvatar(
|
||||
radius: 10,
|
||||
child: Text(channel.state.unreadCount.toString()),
|
||||
child: Text(channel.state!.unreadCount.toString()),
|
||||
)
|
||||
: SizedBox(),
|
||||
);
|
||||
@@ -119,7 +118,7 @@ class ChannelListPage extends StatelessWidget {
|
||||
|
||||
class ChannelPage extends StatelessWidget {
|
||||
const ChannelPage({
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
||||
@@ -33,8 +33,8 @@ class MyApp extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
builder: (context, child) => StreamChat(
|
||||
child: child,
|
||||
client: client,
|
||||
child: child,
|
||||
),
|
||||
home: Container(
|
||||
child: ChannelListPage(),
|
||||
@@ -49,11 +49,10 @@ class ChannelListPage extends StatelessWidget {
|
||||
return Scaffold(
|
||||
body: ChannelsBloc(
|
||||
child: ChannelListView(
|
||||
filter: {
|
||||
'members': {
|
||||
'\$in': [StreamChat.of(context).user.id],
|
||||
}
|
||||
},
|
||||
filter: Filter.in_(
|
||||
'members',
|
||||
[StreamChat.of(context).user!.id],
|
||||
),
|
||||
sort: [SortOption('last_message_at')],
|
||||
pagination: PaginationParams(
|
||||
limit: 20,
|
||||
@@ -67,7 +66,7 @@ class ChannelListPage extends StatelessWidget {
|
||||
|
||||
class ChannelPage extends StatelessWidget {
|
||||
const ChannelPage({
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -93,10 +92,10 @@ class ChannelPage extends StatelessWidget {
|
||||
}
|
||||
|
||||
class ThreadPage extends StatelessWidget {
|
||||
final Message parent;
|
||||
final Message? parent;
|
||||
|
||||
ThreadPage({
|
||||
Key key,
|
||||
Key? key,
|
||||
this.parent,
|
||||
}) : super(key: key);
|
||||
|
||||
@@ -104,7 +103,7 @@ class ThreadPage extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: ThreadHeader(
|
||||
parent: parent,
|
||||
parent: parent!,
|
||||
),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
|
||||
@@ -38,8 +38,8 @@ class MyApp extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
builder: (context, child) => StreamChat(
|
||||
child: child,
|
||||
client: client,
|
||||
child: child,
|
||||
),
|
||||
home: ChannelListPage(),
|
||||
);
|
||||
@@ -52,11 +52,10 @@ class ChannelListPage extends StatelessWidget {
|
||||
return Scaffold(
|
||||
body: ChannelsBloc(
|
||||
child: ChannelListView(
|
||||
filter: {
|
||||
'members': {
|
||||
'\$in': [StreamChat.of(context).user.id],
|
||||
}
|
||||
},
|
||||
filter: Filter.in_(
|
||||
'members',
|
||||
[StreamChat.of(context).user!.id],
|
||||
),
|
||||
sort: [SortOption('last_message_at')],
|
||||
pagination: PaginationParams(
|
||||
limit: 20,
|
||||
@@ -70,7 +69,7 @@ class ChannelListPage extends StatelessWidget {
|
||||
|
||||
class ChannelPage extends StatelessWidget {
|
||||
const ChannelPage({
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -96,7 +95,7 @@ class ChannelPage extends StatelessWidget {
|
||||
List<Message> messages,
|
||||
) {
|
||||
final message = details.message;
|
||||
final isCurrentUser = StreamChat.of(context).user.id == message.user.id;
|
||||
final isCurrentUser = StreamChat.of(context).user!.id == message.user!.id;
|
||||
final textAlign = isCurrentUser ? TextAlign.right : TextAlign.left;
|
||||
final color = isCurrentUser ? Colors.blueGrey : Colors.blue;
|
||||
|
||||
@@ -111,11 +110,11 @@ class ChannelPage extends StatelessWidget {
|
||||
),
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
message.text,
|
||||
message.text!,
|
||||
textAlign: textAlign,
|
||||
),
|
||||
subtitle: Text(
|
||||
message.user.extraData['name'],
|
||||
message.user!.extraData['name'] as String,
|
||||
textAlign: textAlign,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -64,9 +64,9 @@ class MyApp extends StatelessWidget {
|
||||
theme: themeData,
|
||||
builder: (context, child) {
|
||||
return StreamChat(
|
||||
child: child,
|
||||
client: client,
|
||||
streamChatThemeData: customTheme,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
home: ChannelListPage(),
|
||||
@@ -80,11 +80,10 @@ class ChannelListPage extends StatelessWidget {
|
||||
return Scaffold(
|
||||
body: ChannelsBloc(
|
||||
child: ChannelListView(
|
||||
filter: {
|
||||
'members': {
|
||||
'\$in': [StreamChat.of(context).user.id],
|
||||
}
|
||||
},
|
||||
filter: Filter.in_(
|
||||
'members',
|
||||
[StreamChat.of(context).user!.id],
|
||||
),
|
||||
sort: [SortOption('last_message_at')],
|
||||
pagination: PaginationParams(
|
||||
limit: 20,
|
||||
@@ -98,7 +97,7 @@ class ChannelListPage extends StatelessWidget {
|
||||
|
||||
class ChannelPage extends StatelessWidget {
|
||||
const ChannelPage({
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -124,10 +123,10 @@ class ChannelPage extends StatelessWidget {
|
||||
}
|
||||
|
||||
class ThreadPage extends StatelessWidget {
|
||||
final Message parent;
|
||||
final Message? parent;
|
||||
|
||||
ThreadPage({
|
||||
Key key,
|
||||
Key? key,
|
||||
this.parent,
|
||||
}) : super(key: key);
|
||||
|
||||
@@ -135,7 +134,7 @@ class ThreadPage extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: ThreadHeader(
|
||||
parent: parent,
|
||||
parent: parent!,
|
||||
),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
|
||||
@@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
@@ -26,22 +26,12 @@ dependencies:
|
||||
stream_chat_flutter:
|
||||
path: ../
|
||||
stream_chat_persistence:
|
||||
git:
|
||||
url: https://github.com/GetStream/stream-chat-flutter.git
|
||||
ref: develop
|
||||
path: packages/stream_chat_persistence
|
||||
path: ../../stream_chat_persistence
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.0
|
||||
|
||||
dependency_overrides:
|
||||
stream_chat:
|
||||
path: ../../stream_chat
|
||||
stream_chat_flutter_core:
|
||||
path: ../../stream_chat_flutter_core
|
||||
stream_chat_persistence:
|
||||
path: ../../stream_chat_persistence
|
||||
cupertino_icons: ^1.0.2
|
||||
collection: ^1.15.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -6,9 +6,9 @@ import '../utils.dart';
|
||||
|
||||
class AttachmentTitle extends StatelessWidget {
|
||||
const AttachmentTitle({
|
||||
Key key,
|
||||
@required this.attachment,
|
||||
@required this.messageTheme,
|
||||
Key? key,
|
||||
required this.attachment,
|
||||
required this.messageTheme,
|
||||
}) : super(key: key);
|
||||
|
||||
final MessageTheme messageTheme;
|
||||
@@ -19,7 +19,7 @@ class AttachmentTitle extends StatelessWidget {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (attachment.titleLink != null) {
|
||||
launchURL(context, attachment.titleLink);
|
||||
launchURL(context, attachment.titleLink!);
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
@@ -28,17 +28,18 @@ class AttachmentTitle extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
attachment.title,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: messageTheme.messageText.copyWith(
|
||||
color: StreamChatTheme.of(context).colorTheme.accentBlue,
|
||||
fontWeight: FontWeight.bold,
|
||||
if (attachment.title != null)
|
||||
Text(
|
||||
attachment.title!,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: messageTheme.messageText?.copyWith(
|
||||
color: StreamChatTheme.of(context).colorTheme.accentBlue,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (attachment.titleLink != null || attachment.ogScrapeUrl != null)
|
||||
Text(
|
||||
Uri.parse(attachment.titleLink ?? attachment.ogScrapeUrl)
|
||||
Uri.parse(attachment.titleLink ?? attachment.ogScrapeUrl!)
|
||||
.authority
|
||||
.split('.')
|
||||
.reversed
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user