diff --git a/README.md b/README.md index 8d6d17ae..7ce74c78 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,11 @@ Through Chat SDK for flutter, you can efficiently integrate real-time chat into ### How it works -It is simple to implement chat in your client app with Sendbird Chat SDK for Flutter: a user logs in, sees a list of channels, selects or creates an [open channel](https://sendbird.com/docs/chat/v3/ios/guides/open-channel) or a [group channel](https://sendbird.com/docs/chat/v3/ios/guides/group-channel), and, through the use of the [channel event handler](https://sendbird.com/docs/chat/v3/ios/guides/event-delegate), sends messages to the channel, while also receiving them from other users within the channel. +It is simple to implement chat in your client app with Sendbird Chat SDK for Flutter: a user logs in, sees a list of channels, selects or creates an [open channel](https://sendbird.com/docs/chat/v3/flutter/guides/open-channel) or a [group channel](https://sendbird.com/docs/chat/v3/flutter/guides/group-channel), and, through the use of the [channel event handler](https://sendbird.com/docs/chat/v3/flutter/guides/event-handler), sends messages to the channel, while also receiving them from other users within the channel. ### More about Sendbird Chat SDK for flutter -Find out more about Sendbird Chat for Flutter at [Sendbird Docs](). If you have any comments or questions regarding bugs and feature requests, visit [Sendbird community](https://community.sendbird.com). +Find out more about Sendbird Chat for Flutter at [Sendbird Docs](https://sendbird.com/docs/chat/v3/flutter/getting-started/about-chat-sdk). If you have any comments or questions regarding bugs and feature requests, visit [Sendbird community](https://community.sendbird.com).
@@ -35,9 +35,7 @@ The minimum requirements for Chat SDK for Flutter are: - Xcode or Android studio - Dart 2.10.4 -- Flutter 1.22.x - ->__Note__: Flutter 2.0.x aren't compatible yet. +- Flutter 1.22.x or higher ## Getting started @@ -146,7 +144,7 @@ For security reasons, you can also use a session token when a user logs in to Se ### Step 3: Create a new open channel -Create an [open channel](https://sendbird.com/docs/chat/v3/ios/guides/open-channel#2-create-a-channel). Once created, all users in your Sendbird application can easily participate in the channel. +Create an [open channel](https://sendbird.com/docs/chat/v3/flutter/guides/open-channel#2-create-a-channel). Once created, all users in your Sendbird application can easily participate in the channel. ```dart try { @@ -156,7 +154,7 @@ try { } ``` -You can also create a [group channel](https://sendbird.com/docs/chat/v3/ios/guides/group-channel#2-create-a-channel) by [inviting users as new members](https://sendbird.com/docs/chat/v3/ios/guides/group-channel#2-invite-users-as-members) to the channel. +You can also create a [group channel](https://sendbird.com/docs/chat/v3/flutter/guides/group-channel#2-create-a-channel) by [inviting users as new members](https://sendbird.com/docs/chat/v3/flutter/guides/group-channel#2-invite-users-as-members) to the channel. > Note: The majority of the methods used in the following steps are all asynchronous. This means, with asynchronous methods, your client app must receive a result via `await` or `then()` callbacks from Sendbird server through completion handlers before moving on to the next step. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 00000000..60b9fbbf --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,17 @@ +# Defines a default set of lint rules enforced for +# projects at Google. For details and rationale, +# see https://github.com/dart-lang/pedantic#enabled-lints. +include: package:pedantic/analysis_options.yaml + +# For lint rules and documentation, see http://dart-lang.github.io/linter/lints. +# Uncomment to specify additional rules. +linter: + rules: + prefer_final_fields: false + unawaited_futures: false + +analyzer: + exclude: + - example + - lib/**/*.g.dart + - lib/params/message_change_logs_params.g.dart \ No newline at end of file diff --git a/example/main.dart b/example/main.dart new file mode 100644 index 00000000..0d943597 --- /dev/null +++ b/example/main.dart @@ -0,0 +1,29 @@ +import 'package:sendbird_sdk/sendbird_sdk.dart'; + +void main(List arguments) async { + // This example uses the Google Books API to search for books about http. + // https://developers.google.com/books/docs/overview + + final sendbird = SendbirdSdk(appId: 'YOUR-APP-ID'); + + try { + final user = await sendbird.connect('UNIQUE-USER-ID'); + final params = GroupChannelParams() + ..userIds = [user.userId] + ..operatorUserIds = [user.userId] + ..name = 'YOUR_GROUP_NAME' + ..customType = 'CUSTOM_TYPE' + ..isPublic = true; + + // create group channel + final channel = await GroupChannel.createChannel(params); + + channel.sendUserMessageWithText('Hello World', + onCompleted: (message, error) { + // message has been sent successfully + print('${message.message} has been sent!'); + }); + } catch (e) { + // handle error + } +} diff --git a/lib/constant/enums.dart b/lib/constant/enums.dart index da4ffbcb..9667af44 100644 --- a/lib/constant/enums.dart +++ b/lib/constant/enums.dart @@ -19,9 +19,9 @@ extension ChannelTypeExtension on ChannelType { String get urlString { switch (this) { case ChannelType.group: - return "group_channels"; + return 'group_channels'; case ChannelType.open: - return "open_channels"; + return 'open_channels'; default: return null; } @@ -52,7 +52,7 @@ enum Role { none, /// Operator - @JsonValue("operator") + @JsonValue('operator') chat_operator } @@ -499,13 +499,12 @@ enum ChannelQueryIncludeOption { extension IncludeOptionList on List { Map toJson() { - final hasEmpty = this.contains(ChannelQueryIncludeOption.emptyChannel); - final hasMember = this.contains(ChannelQueryIncludeOption.memberList); - final hasFrozen = this.contains(ChannelQueryIncludeOption.frozenChannel); - final hasRead = this.contains(ChannelQueryIncludeOption.readReceipt); - final hasDelivery = - this.contains(ChannelQueryIncludeOption.deliveryReceipt); - final hasMeta = this.contains(ChannelQueryIncludeOption.metaData); + final hasEmpty = contains(ChannelQueryIncludeOption.emptyChannel); + final hasMember = contains(ChannelQueryIncludeOption.memberList); + final hasFrozen = contains(ChannelQueryIncludeOption.frozenChannel); + final hasRead = contains(ChannelQueryIncludeOption.readReceipt); + final hasDelivery = contains(ChannelQueryIncludeOption.deliveryReceipt); + final hasMeta = contains(ChannelQueryIncludeOption.metaData); return { if (hasEmpty) 'show_empty': true, diff --git a/lib/constant/types.dart b/lib/constant/types.dart index dc7ad304..d93614b2 100644 --- a/lib/constant/types.dart +++ b/lib/constant/types.dart @@ -1,7 +1,8 @@ import 'package:sendbird_sdk/core/message/base_message.dart'; import 'package:sendbird_sdk/core/message/file_message.dart'; +import 'package:sendbird_sdk/core/message/user_message.dart'; -typedef void OnUploadProgressCallback(int sentBytes, int totalBytes); -typedef void OnMessageCallback(BaseMessage message, Error error); -typedef void OnFileMessageCallback(FileMessage message, Error error); -typedef void OnUserMessageCallback(FileMessage message, Error error); +typedef OnUploadProgressCallback = void Function(int sentBytes, int totalBytes); +typedef OnMessageCallback = void Function(BaseMessage message, Error error); +typedef OnFileMessageCallback = void Function(FileMessage message, Error error); +typedef OnUserMessageCallback = void Function(UserMessage message, Error error); diff --git a/lib/core/channel/base/base_channel.dart b/lib/core/channel/base/base_channel.dart index f50bf54c..c2bb6925 100644 --- a/lib/core/channel/base/base_channel.dart +++ b/lib/core/channel/base/base_channel.dart @@ -76,7 +76,8 @@ class BaseChannel implements Cacheable { bool fromCache = false; @JsonKey(ignore: true) - bool dirty = false; + @override + bool dirty; /// **WARNING:** Do not use default constructor to initialize manually BaseChannel({ diff --git a/lib/core/channel/base/base_channel_messages.dart b/lib/core/channel/base/base_channel_messages.dart index 0493c575..7077ac11 100644 --- a/lib/core/channel/base/base_channel_messages.dart +++ b/lib/core/channel/base/base_channel_messages.dart @@ -10,7 +10,7 @@ extension Messages on BaseChannel { /// on all other members' end. UserMessage sendUserMessageWithText( String text, { - OnMessageCallback onCompleted, + OnUserMessageCallback onCompleted, }) { final params = UserMessageParams()..message = text; return sendUserMessage( @@ -27,7 +27,7 @@ extension Messages on BaseChannel { /// on all other members' end. UserMessage sendUserMessage( UserMessageParams params, { - OnMessageCallback onCompleted, + OnUserMessageCallback onCompleted, }) { if (params.message == null || params.message.isEmpty) { throw InvalidParameterError(); @@ -77,7 +77,7 @@ extension Messages on BaseChannel { /// on all other members' end. UserMessage resendUserMessage( UserMessage message, { - OnMessageCallback onCompleted, + OnUserMessageCallback onCompleted, }) { if (message == null || message.sendingStatus != MessageSendingStatus.failed) { @@ -118,7 +118,7 @@ extension Messages on BaseChannel { final msg = BaseMessage.msgFromJson(res.payload); return msg; } catch (e) { - throw e; + rethrow; } } @@ -162,7 +162,7 @@ extension Messages on BaseChannel { Duration(seconds: _sdk.options.fileTransferTimeout), onTimeout: () { logger.e('upload timeout'); - if (onCompleted != null) + if (onCompleted != null) { onCompleted( pending..sendingStatus = MessageSendingStatus.failed, SBError( @@ -170,6 +170,7 @@ extension Messages on BaseChannel { code: ErrorCode.fileUploadTimeout, ), ); + } return; }, ); @@ -272,7 +273,7 @@ extension Messages on BaseChannel { final msg = BaseMessage.msgFromJson(res.payload); return msg; } catch (e) { - throw e; + rethrow; } } @@ -364,8 +365,9 @@ extension Messages on BaseChannel { throw InvalidParameterError(); } - if (channelType == ChannelType.group) + if (channelType == ChannelType.group) { params.showSubChannelMessagesOnly = false; + } return _sdk.api.getMessages( channelType: channelType, @@ -387,8 +389,9 @@ extension Messages on BaseChannel { throw InvalidParameterError(); } - if (channelType == ChannelType.group) + if (channelType == ChannelType.group) { params.showSubChannelMessagesOnly = false; + } return _sdk.api.getMessages( channelType: channelType, diff --git a/lib/core/channel/base/base_channel_meta.dart b/lib/core/channel/base/base_channel_meta.dart index f27cb8c6..e8b4480a 100644 --- a/lib/core/channel/base/base_channel_meta.dart +++ b/lib/core/channel/base/base_channel_meta.dart @@ -309,7 +309,7 @@ extension Meta on BaseChannel { throw InvalidParameterError(); } - if (metaArrays == null || metaArrays.length == 0) { + if (metaArrays == null || metaArrays.isEmpty) { throw InvalidParameterError(); } @@ -330,7 +330,7 @@ extension Meta on BaseChannel { throw InvalidParameterError(); } - if (keys == null || keys.length <= 0) { + if (keys == null || keys.isEmpty) { throw InvalidParameterError(); } @@ -353,7 +353,7 @@ extension Meta on BaseChannel { throw InvalidParameterError(); } - if (metaArrays == null || metaArrays.length == 0) { + if (metaArrays == null || metaArrays.isEmpty) { throw InvalidParameterError(); } diff --git a/lib/core/channel/group/features/delivery_status.dart b/lib/core/channel/group/features/delivery_status.dart index bd61c4be..d70fa81f 100644 --- a/lib/core/channel/group/features/delivery_status.dart +++ b/lib/core/channel/group/features/delivery_status.dart @@ -8,10 +8,11 @@ part 'delivery_status.g.dart'; class DeliveryStatus implements Cacheable { final String channelUrl; - @JsonKey(name: "updated") + @JsonKey(name: 'updated') Map updatedDeliveryReceipt; @JsonKey(ignore: true) + @override bool dirty = false; DeliveryStatus({ @@ -30,7 +31,8 @@ class DeliveryStatus implements Cacheable { @override void copyWith(dynamic others) { - if (others is DeliveryStatus) + if (others is DeliveryStatus) { updatedDeliveryReceipt.addAll(others.updatedDeliveryReceipt); + } } } diff --git a/lib/core/channel/group/features/read_status.dart b/lib/core/channel/group/features/read_status.dart index 6f3c0f86..08415ae2 100644 --- a/lib/core/channel/group/features/read_status.dart +++ b/lib/core/channel/group/features/read_status.dart @@ -23,6 +23,7 @@ class ReadStatus implements Cacheable { int timestamp; @JsonKey(ignore: true) + @override bool dirty = false; ReadStatus({ diff --git a/lib/core/channel/group/features/typing_status.dart b/lib/core/channel/group/features/typing_status.dart index 1b1b27c2..29a7507a 100644 --- a/lib/core/channel/group/features/typing_status.dart +++ b/lib/core/channel/group/features/typing_status.dart @@ -9,6 +9,7 @@ class TypingStatus implements Cacheable { User user; int timestamp; + @override bool dirty = false; TypingStatus({ diff --git a/lib/core/channel/group/group_channel.dart b/lib/core/channel/group/group_channel.dart index 0637a8a5..c50a67dd 100644 --- a/lib/core/channel/group/group_channel.dart +++ b/lib/core/channel/group/group_channel.dart @@ -264,9 +264,8 @@ class GroupChannel extends BaseChannel { if (params == null) { throw InvalidParameterError(); } - if (params.channelUrl == null) { - params.channelUrl = channelUrl; - } + params.channelUrl ??= channelUrl; + if (params.channelUrl != channelUrl) { throw InvalidParameterError(); } diff --git a/lib/core/channel/group/group_channel_configuration.dart b/lib/core/channel/group/group_channel_configuration.dart index 2283e190..e1af5157 100644 --- a/lib/core/channel/group/group_channel_configuration.dart +++ b/lib/core/channel/group/group_channel_configuration.dart @@ -17,7 +17,7 @@ extension GroupChannelConfiguration on GroupChannel { ); if (offset != null) messageOffsetTimestamp = offset; - if (hidePreviousMessage) this.clearUnreadCount(); + if (hidePreviousMessage) clearUnreadCount(); isHidden = true; hiddenState = allowAutoUnhide diff --git a/lib/core/channel/group/group_channel_internal.dart b/lib/core/channel/group/group_channel_internal.dart index c8eb1fb4..457c37d2 100644 --- a/lib/core/channel/group/group_channel_internal.dart +++ b/lib/core/channel/group/group_channel_internal.dart @@ -110,11 +110,11 @@ extension GroupChannelInternal on GroupChannel { members.sort((a, b) => a.nickname.compareTo(b.nickname)); final ts = DateTime.now().millisecondsSinceEpoch; - DeliveryStatus delivery = DeliveryStatus( + final delivery = DeliveryStatus( channelUrl: channelUrl, updatedDeliveryReceipt: {newMember.userId: ts}, ); - ReadStatus read = ReadStatus( + final read = ReadStatus( channelType: channelType, channelUrl: channelUrl, timestamp: ts, diff --git a/lib/core/channel/group/group_channel_typing.dart b/lib/core/channel/group/group_channel_typing.dart index 6c23f2f9..a08b413a 100644 --- a/lib/core/channel/group/group_channel_typing.dart +++ b/lib/core/channel/group/group_channel_typing.dart @@ -35,7 +35,7 @@ extension GroupChannelTyping on GroupChannel { bool get isTyping { final typingStatuses = _sdk.cache.findAll(channelKey: channelUrl); - return typingStatuses != null && typingStatuses.length > 0; + return typingStatuses != null && typingStatuses.isNotEmpty; } /// Returns a list of [User] who are currently typing. diff --git a/lib/core/channel/open/open_channel.dart b/lib/core/channel/open/open_channel.dart index 0e247007..46c7de7d 100644 --- a/lib/core/channel/open/open_channel.dart +++ b/lib/core/channel/open/open_channel.dart @@ -123,9 +123,7 @@ class OpenChannel extends BaseChannel { if (params == null) { throw InvalidParameterError(); } - if (params.channelUrl == null) { - params.channelUrl = channelUrl; - } + params.channelUrl ??= channelUrl; if (params.channelUrl != channelUrl) { throw InvalidParameterError(); } diff --git a/lib/core/message/admin_message.dart b/lib/core/message/admin_message.dart index 8d824675..15b865bc 100644 --- a/lib/core/message/admin_message.dart +++ b/lib/core/message/admin_message.dart @@ -72,5 +72,6 @@ class AdminMessage extends BaseMessage { factory AdminMessage.fromJson(Map json) => _$AdminMessageFromJson(json); + @override Map toJson() => _$AdminMessageToJson(this); } diff --git a/lib/core/message/base_message.dart b/lib/core/message/base_message.dart index 62edbd76..871ee724 100644 --- a/lib/core/message/base_message.dart +++ b/lib/core/message/base_message.dart @@ -88,7 +88,7 @@ class BaseMessage { /// Gets an array of meta arrays sorted by chronological order. /// current does not support backward compatibility - @JsonKey(name: "sorted_metaarray") + @JsonKey(name: 'sorted_metaarray') List metaArrays; /// Custom message type @@ -165,7 +165,7 @@ class BaseMessage { /// Returns `true` if this message can be resend. bool isResendable() { - bool resendableError = errorCode == ErrorCode.connectionRequired || + final resendableError = errorCode == ErrorCode.connectionRequired || errorCode == ErrorCode.networkError || errorCode == ErrorCode.ackTimeout || errorCode == ErrorCode.webSocketConnectionClosed || @@ -339,7 +339,7 @@ class BaseMessage { static T msgFromJson(Map json, {ChannelType channelType}) { - String cmd = json["type"] as String; + final cmd = json['type'] as String; T msg; //basemessage backward compatibility - if (json['custom'] != null) json['data'] = json['custom']; @@ -386,7 +386,7 @@ class BaseMessage { /// Map [json] object factory BaseMessage.fromJson(Map json) { - String cmd = json["type"] as String; + final cmd = json['type'] as String; BaseMessage msg; //basemessage backward compatibility - if (json['custom'] != null) json['data'] = json['custom']; diff --git a/lib/core/message/base_message_internal.dart b/lib/core/message/base_message_internal.dart index f45e93b7..08aae18b 100644 --- a/lib/core/message/base_message_internal.dart +++ b/lib/core/message/base_message_internal.dart @@ -10,10 +10,9 @@ extension BaseMessageInternal on BaseMessage { } return mentionedUsers - .where((element) => element.userId == user.userId) - .toList() - .length != - 0; + .where((element) => element.userId == user.userId) + .toList() + .isNotEmpty; } bool mentioned({User user, User byOtherUser}) { @@ -35,6 +34,6 @@ extension BaseMessageInternal on BaseMessage { } bool hasUpdatedLaterThan(int time) { - return this.hasCreatedLaterThan(time) && updatedAt > time; + return hasCreatedLaterThan(time) && updatedAt > time; } } diff --git a/lib/core/message/file_message.dart b/lib/core/message/file_message.dart index 7bf47408..51bb6879 100644 --- a/lib/core/message/file_message.dart +++ b/lib/core/message/file_message.dart @@ -143,6 +143,7 @@ class FileMessage extends BaseMessage { return msg; } + @override Map toJson() => _$FileMessageToJson(this); @override diff --git a/lib/core/message/scheduled_user_message.dart b/lib/core/message/scheduled_user_message.dart index c424aa2f..1ace0714 100644 --- a/lib/core/message/scheduled_user_message.dart +++ b/lib/core/message/scheduled_user_message.dart @@ -20,7 +20,7 @@ class ScheduledUserMessage extends BaseMessage { final int scheduledId; /// Scheduled message date time. (format: "YYYY-MM-DD HH:mm") - @JsonKey(name: "scheduled_dt") + @JsonKey(name: 'scheduled_dt') final String scheduledDateTimeString; /// Scheduled message timezone. (e.g. UTC, America/Los_Angeles, etc) @@ -40,7 +40,7 @@ class ScheduledUserMessage extends BaseMessage { final SBError error; /// Target languages that the message will be translated into - @JsonKey(name: "translation_target_langs") + @JsonKey(name: 'translation_target_langs') final List targetLanguages; ScheduledUserMessage({ @@ -106,6 +106,7 @@ class ScheduledUserMessage extends BaseMessage { factory ScheduledUserMessage.fromJson(Map json) => _$ScheduledUserMessageFromJson(json); + @override Map toJson() => _$ScheduledUserMessageToJson(this); @override diff --git a/lib/core/message/user_message.dart b/lib/core/message/user_message.dart index 89b03c5c..7708c3c4 100644 --- a/lib/core/message/user_message.dart +++ b/lib/core/message/user_message.dart @@ -78,6 +78,7 @@ class UserMessage extends BaseMessage { factory UserMessage.fromJson(Map json) => _$UserMessageFromJson(json); + @override Map toJson() => _$UserMessageToJson(this); @override diff --git a/lib/core/models/command.dart b/lib/core/models/command.dart index f4bc917d..13e9be38 100644 --- a/lib/core/models/command.dart +++ b/lib/core/models/command.dart @@ -50,8 +50,8 @@ class Command { this.payload, }) { if (payload != null) { - this.requestId = requestId != null ? requestId : Uuid().v1(); - payload['req_id'] = this.requestId; + requestId = requestId ?? Uuid().v1(); + payload['req_id'] = requestId; payload.removeWhere((key, value) => value == null); } } @@ -132,17 +132,16 @@ class Command { UserMessageParams params, String requestId, ) { - Map payload = { + final payload = { 'channel_url': channelUrl, 'message': params.message ?? '', 'data': params.data, 'custom_type': params.customType }; - if (params.targetLanguages?.length != 0) { + if (params.targetLanguages.isNotEmpty) { payload['target_langs'] = params.targetLanguages; - payload['translations'] = Map.fromIterable(params.targetLanguages, - key: (e) => e, value: (e) => ''); + payload['translations'] = {for (var e in params.targetLanguages) e: ''}; } if (params.pushOption == PushNotificationDeliveryOption.suppress) { @@ -174,7 +173,7 @@ class Command { int messageId, UserMessageParams params, ) { - Map payload = { + final payload = { 'msg_id': messageId, 'channel_url': channelUrl, 'message': params.message, @@ -194,7 +193,7 @@ class Command { List thumbnails, bool requireAuth, }) { - Map payload = { + final payload = { 'channel_url': channelUrl, if (requireAuth != null) 'require_auth': requireAuth, 'url': params.uploadFile.url, @@ -233,7 +232,7 @@ class Command { static Command buildUpdateFileMessage( String channelUrl, int messageId, FileMessageParams params) { - Map payload = { + final payload = { 'channel_url': channelUrl, 'msg_id': messageId, 'data': params.data, @@ -258,12 +257,13 @@ class Command { } String type; - if (message is UserMessage) + if (message is UserMessage) { type = CommandType.userMessageUpdate; - else if (message is FileMessage) + } else if (message is FileMessage) { type = CommandType.fileMessageUpdate; - else + } else { throw InvalidParameterError(); + } return Command(cmd: type, payload: { 'channel_url': message.channelUrl, diff --git a/lib/core/models/member.dart b/lib/core/models/member.dart index f6a9a621..303dad64 100644 --- a/lib/core/models/member.dart +++ b/lib/core/models/member.dart @@ -61,6 +61,7 @@ class Member extends User { factory Member.fromJson(Map json) => _$MemberFromJson(json); + @override Map toJson() => _$MemberToJson(this); @override diff --git a/lib/core/models/og_image.dart b/lib/core/models/og_image.dart index a57e55fa..c71728a6 100644 --- a/lib/core/models/og_image.dart +++ b/lib/core/models/og_image.dart @@ -7,9 +7,11 @@ part 'og_image.g.dart'; @JsonSerializable() class OGImage implements OGMedia, OGDisplayable { /// Image url + @override final String url; /// Image secure url + @override final String secureUrl; /// Image type @@ -19,9 +21,11 @@ class OGImage implements OGMedia, OGDisplayable { final String alt; /// Image width + @override final int width; /// Image height + @override final int height; OGImage({ diff --git a/lib/core/models/reaction.dart b/lib/core/models/reaction.dart index 468a40c5..3589e086 100644 --- a/lib/core/models/reaction.dart +++ b/lib/core/models/reaction.dart @@ -21,8 +21,7 @@ class Reaction { this.userIds, this.updatedAt, }) { - updatedAts = - Map.fromIterable(userIds, key: (e) => e, value: (e) => updatedAt); + updatedAts = {for (var e in userIds) e: updatedAt}; } bool merge(ReactionEvent event) { diff --git a/lib/core/models/reconnect_configuration.dart b/lib/core/models/reconnect_configuration.dart index ccb8e19c..82d450a6 100644 --- a/lib/core/models/reconnect_configuration.dart +++ b/lib/core/models/reconnect_configuration.dart @@ -4,16 +4,16 @@ part 'reconnect_configuration.g.dart'; @JsonSerializable() class ReconnectConfiguration { - @JsonKey(name: "interval") + @JsonKey(name: 'interval') double interval; - @JsonKey(name: "max_interval") + @JsonKey(name: 'max_interval') double maxInterval; - @JsonKey(name: "mul") + @JsonKey(name: 'mul') int multiplier; - @JsonKey(name: "retry_cnt") + @JsonKey(name: 'retry_cnt') int maximumRetryCount; bool get enabledInfinitelyRetry => maximumRetryCount < 0; diff --git a/lib/core/models/sender.dart b/lib/core/models/sender.dart index 8c712c67..05f25d0e 100644 --- a/lib/core/models/sender.dart +++ b/lib/core/models/sender.dart @@ -47,7 +47,7 @@ class Sender extends User { ); factory Sender.fromUser(User user, BaseChannel channel) { - Sender sender = Sender.fromJson(user.toJson()); + final sender = Sender.fromJson(user.toJson()); if (channel is GroupChannel) { sender.role = channel.myRole; } else if (channel is OpenChannel) { @@ -66,6 +66,7 @@ class Sender extends User { return _$SenderFromJson(json); } + @override Map toJson() => _$SenderToJson(this); @override diff --git a/lib/core/models/unread_count_info.dart b/lib/core/models/unread_count_info.dart index ed5acfee..ef9bb310 100644 --- a/lib/core/models/unread_count_info.dart +++ b/lib/core/models/unread_count_info.dart @@ -11,7 +11,7 @@ class UnreadCountInfo { UnreadCountInfo({this.all, this.customTypes, this.ts}); bool copyWith(UnreadCountInfo others) { - bool didChange = false; + var didChange = false; ts = others.ts; diff --git a/lib/core/models/user.dart b/lib/core/models/user.dart index a5e5c8c3..ded805b9 100644 --- a/lib/core/models/user.dart +++ b/lib/core/models/user.dart @@ -56,7 +56,7 @@ class User { @JsonKey(defaultValue: {}, name: 'metadata') Map metaData; - @JsonKey(name: "require_auth_for_profile_image") + @JsonKey(name: 'require_auth_for_profile_image') bool requireAuth; String sessionToken; @@ -130,7 +130,7 @@ class User { factory User.fromJson(Map json) { if (json['guest_id'] != null) json['user_id'] = json['guest_id']; if (json['session_tokens'] != null && - (json['session_tokens'] as List).length > 0) { + (json['session_tokens'] as List).isEmpty) { final tokens = List.from(json['session_tokens'] as List); json['session_token'] = tokens?.first['session_token']; } diff --git a/lib/events/channel_event.dart b/lib/events/channel_event.dart index 2ea7582d..1f007f4a 100644 --- a/lib/events/channel_event.dart +++ b/lib/events/channel_event.dart @@ -43,24 +43,24 @@ class ChannelEvent implements BaseEvent { this.messageOffset, }); - int get memberCount => data != null ? data["member_count"] : null; + int get memberCount => data != null ? data['member_count'] : null; int get joinedMemberCount => - data != null ? data["joined_member_count"] : null; - int get participantCount => data != null ? data["participant_count"] : null; - bool get allowAutoUnhide => data != null ? data["allow_auto_unhide"] : null; - bool get hidePreviousMessage => data["hide_previous_messages"]; - Member get inviter => data != null && data["inviter"] != null - ? Member.fromJson(data["inviter"]) + data != null ? data['joined_member_count'] : null; + int get participantCount => data != null ? data['participant_count'] : null; + bool get allowAutoUnhide => data != null ? data['allow_auto_unhide'] : null; + bool get hidePreviousMessage => data['hide_previous_messages']; + Member get inviter => data != null && data['inviter'] != null + ? Member.fromJson(data['inviter']) : null; - Member get invitee => data != null && data["invitee"] != null - ? Member.fromJson(data["invitee"]) + Member get invitee => data != null && data['invitee'] != null + ? Member.fromJson(data['invitee']) : null; List get invitees { - if (data != null && data["invitees"] == null) { + if (data != null && data['invitees'] == null) { return []; } - final dics = data["invitees"] as List; + final dics = data['invitees'] as List; final members = dics.map((e) => Member.fromJson(e)).toList(); // members.forEach((e) => e.state = MemberState.invited); return members; @@ -69,8 +69,8 @@ class ChannelEvent implements BaseEvent { User get user => data != null ? User.fromJson(data) : null; List get users { - if (data["users"] != null) { - final dics = data["users"] as List; + if (data['users'] != null) { + final dics = data['users'] as List; final users = dics.map((e) => Member.fromJson(e)).toList(); // users.forEach((e) => e.state = MemberState.invited); return users; @@ -80,18 +80,18 @@ class ChannelEvent implements BaseEvent { } List get operators { - if (data["operators"] == null) { + if (data['operators'] == null) { return []; } - final dics = data["operators"] as List; + final dics = data['operators'] as List; final members = dics.map((e) => Member.fromJson(e)).toList(); // members.forEach((e) => e.state = MemberState.invited); return members; } int get invitedAt => - category == ChannelEventCategory.invite ? data["invited_at"] : 0; + category == ChannelEventCategory.invite ? data['invited_at'] : 0; factory ChannelEvent.fromJson(Map json) => _$ChannelEventFromJson(json); diff --git a/lib/events/session_event.dart b/lib/events/session_event.dart index 7fb0d672..c7e81ee2 100644 --- a/lib/events/session_event.dart +++ b/lib/events/session_event.dart @@ -15,7 +15,7 @@ class SessionEvent extends BaseEvent { final String key; - String get sessionKey => key ?? newKey ?? null; + String get sessionKey => key ?? newKey; SessionEvent({this.expiresIn, this.newKey, this.ekey, this.key}); diff --git a/lib/managers/command_manager.dart b/lib/managers/command_manager.dart index bbb94c59..c816a237 100644 --- a/lib/managers/command_manager.dart +++ b/lib/managers/command_manager.dart @@ -35,9 +35,9 @@ import 'package:sendbird_sdk/utils/logger.dart'; import 'package:sendbird_sdk/utils/parsers.dart'; class CommandManager with SdkAccessor { - Map _ackTimers = {}; - Map> _completers = {}; - AsyncQueue _queue = AsyncQueue(); + final Map _ackTimers = {}; + final Map> _completers = {}; + final AsyncQueue _queue = AsyncQueue(); void cleanUp() { _ackTimers.removeWhere((key, value) => true); @@ -47,10 +47,11 @@ class CommandManager with SdkAccessor { void clearCompleters({Error error}) { _completers.forEach((key, value) { - if (error != null) + if (error != null) { value.completeError(error); - else + } else { value.complete(); + } }); _completers.removeWhere((key, value) => true); } @@ -76,14 +77,14 @@ class CommandManager with SdkAccessor { await ConnectionManager.readyToExecuteWSRequest(); } catch (e) { _ackTimers.remove(cmd.requestId)?.cancel(); - throw e; + rethrow; } try { webSocket.send(cmd.encode()); } catch (e) { _ackTimers.remove(cmd.requestId)?.cancel(); - throw e; + rethrow; } // } else { // ackTimers[cmd.requestId].cancel(); @@ -98,7 +99,7 @@ class CommandManager with SdkAccessor { }); _ackTimers[cmd.requestId] = timer; - final completer = new Completer(); + final completer = Completer(); _completers[cmd.requestId] = completer; return completer.future; } else { @@ -133,35 +134,35 @@ class CommandManager with SdkAccessor { logger.i('Processing Socket event\n$cmdString\n$payloadString'); Function(Command) fnc; - if (cmd.isError || cmd.hasError) + if (cmd.isError || cmd.hasError) { fnc = _processError; - else if (cmd.isLogin && cmd.requestId != null) + } else if (cmd.isLogin && cmd.requestId != null) { fnc = _processSessionRefresh; - else if (cmd.isLogin) + } else if (cmd.isLogin) { fnc = _processLogin; - else if (cmd.isSessionExpired) + } else if (cmd.isSessionExpired) { fnc = _processSessionExpired; - else if (cmd.isNewMessage) + } else if (cmd.isNewMessage) { fnc = _processNewMessage; - else if (cmd.isUpdatedMessage) + } else if (cmd.isUpdatedMessage) { fnc = _processUpdateMessage; - else if (cmd.isDeletedMessage) + } else if (cmd.isDeletedMessage) { fnc = _processDeleteMessage; - else if (cmd.isMemberCountChange) + } else if (cmd.isMemberCountChange) { fnc = _processMemberCountChange; - else if (cmd.isRead) + } else if (cmd.isRead) { fnc = _processRead; - else if (cmd.isDelivery) + } else if (cmd.isDelivery) { fnc = _processDelivery; - else if (cmd.isThread) + } else if (cmd.isThread) { fnc = _processThread; - else if (cmd.isReaction) + } else if (cmd.isReaction) { fnc = _processReaction; - else if (cmd.isUserEvent) + } else if (cmd.isUserEvent) { fnc = _processUserEvent; - else if (cmd.isSystemEvent) + } else if (cmd.isSystemEvent) { fnc = _processSystemEvent; - else {/*not handle command*/} + } else {/*not handle command*/} if (fnc != null) { final op = AsyncTask(func: fnc, arg: cmd); @@ -340,10 +341,12 @@ class CommandManager with SdkAccessor { eventManager.notifyMessageUpdate(channel, message); - if (shouldCallChannelChanged) + if (shouldCallChannelChanged) { eventManager.notifyChannelChanged(channel); - if (shouldCallMentionReceived) + } + if (shouldCallMentionReceived) { eventManager.notifyMentionReceived(channel, message); + } } } catch (e) { logger.w('Aborted ${cmd.cmd} ' + e.toString()); @@ -398,7 +401,7 @@ class CommandManager with SdkAccessor { Future _processRead(Command cmd) async { try { - ReadStatus status = ReadStatus.fromJson(cmd.payload); + final status = ReadStatus.fromJson(cmd.payload); status.saveToCache(); final channel = await GroupChannel.getChannel(status.channelUrl); @@ -420,11 +423,11 @@ class CommandManager with SdkAccessor { Future _processDelivery(Command cmd) async { try { - DeliveryStatus status = DeliveryStatus.fromJson(cmd.payload); + final status = DeliveryStatus.fromJson(cmd.payload); final channel = await GroupChannel.getChannel(status.channelUrl); final currUserId = appState.currentUser.userId; - bool shouldCallDelivery = true; + var shouldCallDelivery = true; if (status.updatedDeliveryReceipt.length == 1 && status.updatedDeliveryReceipt[currUserId] != null) { //not to call @@ -443,7 +446,7 @@ class CommandManager with SdkAccessor { Future _processThread(Command cmd) async { try { - ThreadInfoUpdateEvent event = ThreadInfoUpdateEvent.fromJson(cmd.payload); + final event = ThreadInfoUpdateEvent.fromJson(cmd.payload); final channel = await GroupChannel.getChannel(event.channelUrl); eventManager.notifyChannelThreadUpdated(channel, event); } catch (e) { @@ -453,7 +456,7 @@ class CommandManager with SdkAccessor { Future _processReaction(Command cmd) async { try { - ReactionEvent event = ReactionEvent.fromJson(cmd.payload); + final event = ReactionEvent.fromJson(cmd.payload); final channel = await BaseChannel.getBaseChannel( event.channelType, event.channelUrl, @@ -478,7 +481,7 @@ class CommandManager with SdkAccessor { // System Future _processSystemEvent(Command cmd) async { - ChannelEvent event = ChannelEvent.fromJson(cmd.payload); + final event = ChannelEvent.fromJson(cmd.payload); switch (event.category) { case ChannelEventCategory.typingStart: @@ -551,9 +554,9 @@ class CommandManager with SdkAccessor { Future _processTyping(ChannelEvent event, bool start) async { try { - User user = User.fromJson(event.data); + final user = User.fromJson(event.data); final channel = await GroupChannel.getChannel(event.channelUrl); - TypingStatus status = TypingStatus( + final status = TypingStatus( channelType: ChannelType.group, channelUrl: event.channelUrl, user: user, @@ -574,7 +577,7 @@ class CommandManager with SdkAccessor { Future _processBan(ChannelEvent event, bool banned) async { try { - User user = User.fromJson(event.data); + final user = User.fromJson(event.data); final channel = await BaseChannel.getBaseChannel( event.channelType, event.channelUrl, @@ -600,8 +603,9 @@ class CommandManager with SdkAccessor { } } eventManager.notifyUserBanned(channel, user); - } else + } else { eventManager.notifyUserUnbanned(channel, user); + } } catch (e) { logger.w('Aborted ${event.category.toString()} ' + e.toString()); } @@ -609,7 +613,7 @@ class CommandManager with SdkAccessor { Future _processMute(ChannelEvent event, bool muted) async { try { - User user = User.fromJson(event.data); + final user = User.fromJson(event.data); final channel = await BaseChannel.getBaseChannel( event.channelType, event.channelUrl, @@ -619,15 +623,16 @@ class CommandManager with SdkAccessor { channel.myMutedState = muted ? MuteState.muted : MuteState.unmuted; } - Member member = + final member = channel.members.firstWhere((e) => e.userId == user.userId); member?.isMuted = muted; } - if (muted) + if (muted) { eventManager.notifyUserMuted(channel, user); - else + } else { eventManager.notifyUserUnmuted(channel, user); + } } catch (e) { logger.w('Aborted ${event.category.toString()} ' + e.toString()); } @@ -641,7 +646,7 @@ class CommandManager with SdkAccessor { } if (joined) { - for (Member member in event.users) { + for (final member in event.users) { if (!channel.isSuper) { channel.addMember(member); } @@ -653,7 +658,7 @@ class CommandManager with SdkAccessor { eventManager.notifyChannelMemberCountChange([channel]); } } else { - Member member = Member.fromJson(event.data); + final member = Member.fromJson(event.data); if (!channel.isSuper) { channel.removeMember(member.userId); } @@ -685,7 +690,7 @@ class CommandManager with SdkAccessor { channel.addMember(event.inviter); } - for (Member member in event.invitees) { + for (final member in event.invitees) { if (!channel.isSuper) { channel.addMember(member); } @@ -767,10 +772,11 @@ class CommandManager with SdkAccessor { ); channel.isFrozen = frozen; - if (frozen) + if (frozen) { eventManager.notifyChannelFrozen(channel); - else + } else { eventManager.notifyChannelUnfrozen(channel); + } } catch (e) { logger.w('Aborted ${event.category.toString()} ' + e.toString()); } @@ -794,10 +800,11 @@ class CommandManager with SdkAccessor { channel.isHidden = hidden; channel.hiddenState = event.hiddenState; - if (hidden) + if (hidden) { eventManager.notifyChannelHidden(channel); - else + } else { eventManager.notifyChannelChanged(channel); + } } catch (e) { logger.w('Aborted ${event.category.toString()} ' + e.toString()); } @@ -818,9 +825,9 @@ class CommandManager with SdkAccessor { timestamp: event.ts, ); - final created = Map.from(event.data["created"] ?? {}); - final updated = Map.from(event.data["updated"] ?? {}); - final deleted = List.from(event.data["deleted"] ?? []); + final created = Map.from(event.data['created'] ?? {}); + final updated = Map.from(event.data['updated'] ?? {}); + final deleted = List.from(event.data['deleted'] ?? []); cachedMetaData.addMap(created, event.ts); cachedMetaData.addMap(updated, event.ts); @@ -877,10 +884,12 @@ class CommandManager with SdkAccessor { event.channelUrl, ); if (channel is GroupChannel) { - if (!channel.canChangeUnreadMessageCount) + if (!channel.canChangeUnreadMessageCount) { channel.unreadMessageCount = 0; - if (!channel.canChangeUnreadMentionCount) + } + if (!channel.canChangeUnreadMentionCount) { channel.unreadMentionCount = 0; + } } channel.saveToCache(); eventManager.notifyChannelChanged(channel); @@ -898,7 +907,7 @@ class CommandManager with SdkAccessor { } Future _processUserEvent(Command cmd) async { - UserEvent event = UserEvent.fromJson(cmd.payload); + final event = UserEvent.fromJson(cmd.payload); switch (event.category) { case UserEventCategory.block: _processBlock(event); diff --git a/lib/managers/connection_manager.dart b/lib/managers/connection_manager.dart index d6599f09..221a9185 100644 --- a/lib/managers/connection_manager.dart +++ b/lib/managers/connection_manager.dart @@ -41,7 +41,7 @@ class ConnectionManager { final sdk = SendbirdSdk().getInternal(); final sessionKey = await sdk.sessionManager.getSessionKey(); - final hasValidSession = sessionKey != null && sessionKey.length > 0; + final hasValidSession = sessionKey != null && sessionKey.isNotEmpty; final hasToken = sdk.api.token != null; if (hasValidSession || hasToken) { return; @@ -67,7 +67,7 @@ class ConnectionManager { } static void flushCompleters({SBError error}) { - while (_queue.length > 0) { + while (_queue.isNotEmpty) { final completer = _queue.removeAt(0); if (error != null) { completer.completeError(error); diff --git a/lib/managers/event_manager.dart b/lib/managers/event_manager.dart index 2e7ba530..66980ea5 100644 --- a/lib/managers/event_manager.dart +++ b/lib/managers/event_manager.dart @@ -308,9 +308,9 @@ class EventManager { void notifyMetaDataChanged(BaseChannel channel, Map data) { _channelHandlers.values.forEach((element) { - final created = Map.from(data["created"] ?? {}); - final updated = Map.from(data["updated"] ?? {}); - final deleted = List.from(data["deleted"] ?? []); + final created = Map.from(data['created'] ?? {}); + final updated = Map.from(data['updated'] ?? {}); + final deleted = List.from(data['deleted'] ?? []); if (created.isNotEmpty) element.onMetaDataCreated(channel, created); if (updated.isNotEmpty) element.onMetaDataUpdated(channel, updated); @@ -321,9 +321,9 @@ class EventManager { void notifyMetaCountersChanged( BaseChannel channel, Map data) { _channelHandlers.values.forEach((element) { - final created = Map.from(data["created"] ?? {}); - final updated = Map.from(data["updated"] ?? {}); - final deleted = List.from(data["deleted"] ?? []); + final created = Map.from(data['created'] ?? {}); + final updated = Map.from(data['updated'] ?? {}); + final deleted = List.from(data['deleted'] ?? []); if (created.isNotEmpty) element.onMetaCountersCreated(channel, created); if (updated.isNotEmpty) element.onMetaCountersUpdated(channel, updated); diff --git a/lib/managers/session_manager.dart b/lib/managers/session_manager.dart index 791eed33..f56246e5 100644 --- a/lib/managers/session_manager.dart +++ b/lib/managers/session_manager.dart @@ -68,10 +68,8 @@ class SessionManager with SdkAccessor { /// Get current `sessionKey` from prefs Future getSessionKey() async { if (_sessionKey != null) return _sessionKey; - String decryptedKey = await _decryptedSessionKey(); - if (_sessionKey == null) { - _sessionKey = decryptedKey; - } + final decryptedKey = await _decryptedSessionKey(); + _sessionKey ??= decryptedKey; return decryptedKey; } @@ -150,8 +148,8 @@ class SessionManager with SdkAccessor { // sessionPath = encryptedData.base64; prefs.setString(_sessionKeyPath, encryptedData.base64); - logger.i('encryption completed userId: $base64UserId ' + - 'sessionKey: $encryptedData'); + logger.i( + 'encryption completed userId: $base64UserId sessionKey: $encryptedData'); } // Updates session and notify diff --git a/lib/params/base_message_params.dart b/lib/params/base_message_params.dart index 7f3e112c..05769f2b 100644 --- a/lib/params/base_message_params.dart +++ b/lib/params/base_message_params.dart @@ -56,15 +56,16 @@ class BaseMessageParams { } Map toJson() { - Map ret = {}; - ret['custom_type'] = customType; - ret['data'] = data; - ret['mention_type'] = mentionType?.asString(); - ret['mentioned_user_ids'] = mentionedUserIds; - ret['sorted_metaarray'] = metaArrays?.map((e) => e.toJson())?.toList(); - if (pushOption == PushNotificationDeliveryOption.suppress) - ret['push_option'] = pushOption.asString(); - if (parentMessageId > 0) ret['parent_message_id'] = parentMessageId; + final ret = { + 'custom_type': customType, + 'data': data, + 'mention_type': mentionType?.asString(), + 'mentioned_user_ids': mentionedUserIds, + 'sorted_metaarray': metaArrays?.map((e) => e.toJson())?.toList(), + if (pushOption == PushNotificationDeliveryOption.suppress) + 'push_option': pushOption.asString(), + if (parentMessageId > 0) 'parent_message_id': parentMessageId, + }; ret.removeWhere((key, value) => value == null); return ret; diff --git a/lib/params/file_message_params.dart b/lib/params/file_message_params.dart index dc626321..3d796a16 100644 --- a/lib/params/file_message_params.dart +++ b/lib/params/file_message_params.dart @@ -50,6 +50,7 @@ class FileMessageParams extends BaseMessageParams { ); } + @override Map toJson() { final ret = super.toJson(); ret['url'] = uploadFile?.url; diff --git a/lib/params/message_list_params.dart b/lib/params/message_list_params.dart index 0a12ea27..7c53ccb3 100644 --- a/lib/params/message_list_params.dart +++ b/lib/params/message_list_params.dart @@ -8,17 +8,17 @@ part 'message_list_params.g.dart'; class MessageListParams { /// The number of messages to retrieve that were sent before the /// specified timestamp or message ID. - @JsonKey(name: "prev_limit") + @JsonKey(name: 'prev_limit') int previousResultSize = 10; /// The number of messages to retrieve that were sent after the /// specified timestamp or message ID. - @JsonKey(name: "next_limit") + @JsonKey(name: 'next_limit') int nextResultSize = 0; /// Determines whether to include the messages with the matching /// timestamp or message ID in the results. - @JsonKey(name: "include") + @JsonKey(name: 'include') bool isInclusive = false; /// Determines whether to sort the retrieved messages in reverse @@ -40,7 +40,7 @@ class MessageListParams { /// Determines whether to include the metaarray information of the /// messages in the results. default value is false - @JsonKey(name: "with_sorted_meta_array") + @JsonKey(name: 'with_sorted_meta_array') bool includeMetaArray = false; /// Determines whether to include the reactions to the messages diff --git a/lib/params/message_retrieval_params.dart b/lib/params/message_retrieval_params.dart index 4e481a1a..302abcca 100644 --- a/lib/params/message_retrieval_params.dart +++ b/lib/params/message_retrieval_params.dart @@ -16,7 +16,7 @@ class MessageRetrievalParams { int messageId; /// Determines whether the metaarray of the message is included in the results. - @JsonKey(name: "with_sorted_meta_array") + @JsonKey(name: 'with_sorted_meta_array') bool includeMetaArray = false; /// Determines whether to include the parent message text in the diff --git a/lib/params/scheduled_user_message_params.dart b/lib/params/scheduled_user_message_params.dart index b000cf65..42c20849 100644 --- a/lib/params/scheduled_user_message_params.dart +++ b/lib/params/scheduled_user_message_params.dart @@ -35,6 +35,7 @@ class ScheduledUserMessageParams extends UserMessageParams { metaArrays: metaArrays, ); + @override Map toJson() { final ret = super.toJson(); ret['scheduled_dt'] = '$scheduledDateString $timezone'; diff --git a/lib/params/threaded_message_list_params.dart b/lib/params/threaded_message_list_params.dart index 40967d12..c022e481 100644 --- a/lib/params/threaded_message_list_params.dart +++ b/lib/params/threaded_message_list_params.dart @@ -42,7 +42,7 @@ class ThreadedMessageListParams { /// Determines whether to include the metaarray information of the /// messages in the results. - @JsonKey(name: "with_sorted_meta_array") + @JsonKey(name: 'with_sorted_meta_array') bool includeMetaArray = false; /// Determines whether to include the reactions to the messages diff --git a/lib/params/user_message_params.dart b/lib/params/user_message_params.dart index 44780269..f986de6a 100644 --- a/lib/params/user_message_params.dart +++ b/lib/params/user_message_params.dart @@ -35,6 +35,7 @@ class UserMessageParams extends BaseMessageParams { targetLanguages = userMessage.translations?.keys?.toList() ?? [], super.withMessage(userMessage, deepCopy: deepCopy); + @override Map toJson() { final ret = super.toJson(); ret['message'] = message; diff --git a/lib/query/application_user_list_query.dart b/lib/query/application_user_list_query.dart index 7b97f315..6d64be93 100644 --- a/lib/query/application_user_list_query.dart +++ b/lib/query/application_user_list_query.dart @@ -47,5 +47,6 @@ class ApplicationUserListQuery extends UserListQuery { } // Json Serialization + @override Map toJson() => _$ApplicationUserListQueryToJson(this); } diff --git a/lib/query/group_channel_list_query.dart b/lib/query/group_channel_list_query.dart index 16008e58..ecf44136 100644 --- a/lib/query/group_channel_list_query.dart +++ b/lib/query/group_channel_list_query.dart @@ -135,7 +135,7 @@ class GroupChannelListQuery extends QueryBase { loading = true; - List options = [ + final options = [ if (includeFrozenChannel) ChannelQueryIncludeOption.frozenChannel, if (includeEmptyChannel) ChannelQueryIncludeOption.emptyChannel, if (includeMemberList) ChannelQueryIncludeOption.memberList, diff --git a/lib/query/open_channel_list_query.dart b/lib/query/open_channel_list_query.dart index aaf87580..50cb74a7 100644 --- a/lib/query/open_channel_list_query.dart +++ b/lib/query/open_channel_list_query.dart @@ -36,7 +36,7 @@ class OpenChannelListQuery extends QueryBase { loading = true; - List options = [ + final options = [ if (includeFrozenChannel) ChannelQueryIncludeOption.frozenChannel, if (includeMetaData) ChannelQueryIncludeOption.metaData ]; diff --git a/lib/query/previous_message_list_query.dart b/lib/query/previous_message_list_query.dart index 7f122784..eca33977 100644 --- a/lib/query/previous_message_list_query.dart +++ b/lib/query/previous_message_list_query.dart @@ -94,7 +94,7 @@ class PreviousMessageListQuery extends QueryBase { params: params.toJson(), timestamp: _timestamp); - _timestamp = res.length != 0 ? res.last.createdAt : null; + _timestamp = res.isNotEmpty ? res.last.createdAt : null; loading = false; token = ''; diff --git a/lib/query/public_group_channel_list_query.dart b/lib/query/public_group_channel_list_query.dart index 51467791..11439973 100644 --- a/lib/query/public_group_channel_list_query.dart +++ b/lib/query/public_group_channel_list_query.dart @@ -65,7 +65,7 @@ class PublicGroupChannelListQuery extends QueryBase { loading = true; - List options = [ + final options = [ if (includeFrozenChannel) ChannelQueryIncludeOption.frozenChannel, if (includeEmptyChannel) ChannelQueryIncludeOption.emptyChannel, if (includeMemberList) ChannelQueryIncludeOption.memberList, diff --git a/lib/query/user_list_query.dart b/lib/query/user_list_query.dart index f72cb64b..4f297d01 100644 --- a/lib/query/user_list_query.dart +++ b/lib/query/user_list_query.dart @@ -43,8 +43,9 @@ class UserListQuery extends QueryBase { switch (queryType) { case UserListQueryType.banned: case UserListQueryType.muted: - if (channelType == null || channelUrl == null) + if (channelType == null || channelUrl == null) { throw InvalidParameterError(); + } break; case UserListQueryType.participants: if (channelUrl == null) throw InvalidParameterError(); diff --git a/lib/sdk/internal/sendbird_sdk_internal.dart b/lib/sdk/internal/sendbird_sdk_internal.dart index 8a330c14..b00673a4 100644 --- a/lib/sdk/internal/sendbird_sdk_internal.dart +++ b/lib/sdk/internal/sendbird_sdk_internal.dart @@ -5,7 +5,7 @@ import 'dart:io'; import 'package:connectivity/connectivity.dart'; import 'package:flutter/widgets.dart'; -import 'package:sendbird_sdk/constant/contants.dart' as Constants; +import 'package:sendbird_sdk/constant/contants.dart' as constants; import 'package:sendbird_sdk/constant/enums.dart'; import 'package:sendbird_sdk/core/models/error.dart'; import 'package:sendbird_sdk/core/models/options.dart'; @@ -51,10 +51,10 @@ class SendbirdSdkInternal with WidgetsBindingObserver { AsyncQueue _commandQueue = AsyncQueue(); Map _extensions = {}; List _extraDatas = [ - Constants.sbExtraDataPremiumFeatureList, - Constants.sbExtraDataFileUploadSizeLimit, - Constants.sbExtraDataApplicationAttributes, - Constants.sbExtraDataEmojiHash, + constants.sbExtraDataPremiumFeatureList, + constants.sbExtraDataFileUploadSizeLimit, + constants.sbExtraDataApplicationAttributes, + constants.sbExtraDataEmojiHash, ]; //should only keep one instance @@ -129,15 +129,16 @@ class SendbirdSdkInternal with WidgetsBindingObserver { try { _cmdManager.processCommand(cmd); } catch (e) { - throw e; + rethrow; } }, onError: (e, s) { //handle error how to toss this..? //get waiting func and error? - if (_loginCompleter != null) + if (_loginCompleter != null) { _loginCompleter?.completeError(e); - else + } else { logger.e('fatal error thrown ${e.toString()}'); + } // throw e; }); } @@ -216,7 +217,7 @@ class SendbirdSdkInternal with WidgetsBindingObserver { ..apiHost = apiHost; _api.initialize(baseUrl: apiHost, headers: { - 'SB-User-Agent': this._sbUserAgent, + 'SB-User-Agent': _sbUserAgent, 'User-Agent': '$platform/$sdk_version/${Platform.operatingSystem.toLowerCase()}', }); @@ -233,7 +234,7 @@ class SendbirdSdkInternal with WidgetsBindingObserver { 'key': sessionKey else 'user_id': userId, - 'SB-User-Agent': this._sbUserAgent, + 'SB-User-Agent': _sbUserAgent, 'include_extra_data': _extraDatas.join(','), 'expiring_session': _eventManager.getHandler(type: EventType.session) != null ? '1' : '0', @@ -324,7 +325,7 @@ class SendbirdSdkInternal with WidgetsBindingObserver { if (state == AppLifecycleState.resumed) _handleEnterForeground(); } - _handleEnterBackground() { + void _handleEnterBackground() { _cache.markAsDirtyAll(); //clear all timers _state.connected = false; @@ -333,14 +334,15 @@ class SendbirdSdkInternal with WidgetsBindingObserver { _webSocket?.close(); } - _handleEnterForeground() async { - if (_state.currentUser != null) + void _handleEnterForeground() async { + if (_state.currentUser != null) { await connect(userId: _state.userId, reconnect: true); + } } void _listenConnectionEvents() { //NOTE: do not run connectivity on test - bool isTest = Platform.environment['FLUTTER_TEST'] == 'true'; + final isTest = Platform.environment['FLUTTER_TEST'] == 'true'; if (!isTest) { _connectionSub = Connectivity() .onConnectivityChanged @@ -369,7 +371,7 @@ class SendbirdSdkInternal with WidgetsBindingObserver { } String get _sbUserAgent { - final uikitVersion = _extensions[Constants.sbExtensionKeyUIKit]; + final uikitVersion = _extensions[constants.sbExtensionKeyUIKit]; final core = '/c$sdk_version'; final uikit = uikitVersion != null ? '/u$uikitVersion' : ''; final os = '/o${Platform.operatingSystem.toLowerCase()}'; @@ -377,8 +379,8 @@ class SendbirdSdkInternal with WidgetsBindingObserver { } void addVersionExtension(String key, String version) { - if (key != Constants.sbExtensionKeyUIKit || - key != Constants.sbExtensionKeySyncManager) { + if (key != constants.sbExtensionKeyUIKit || + key != constants.sbExtensionKeySyncManager) { return; } _extensions[key] = version; diff --git a/lib/sdk/sendbird_sdk_api.dart b/lib/sdk/sendbird_sdk_api.dart index 2bad8af2..638d82f7 100644 --- a/lib/sdk/sendbird_sdk_api.dart +++ b/lib/sdk/sendbird_sdk_api.dart @@ -405,8 +405,9 @@ class SendbirdSdk { /// Mark list of group channels with [channelUrls] as read. Future markAsRead({@required List channelUrls}) async { - if (channelUrls == null || channelUrls.isEmpty) + if (channelUrls == null || channelUrls.isEmpty) { throw InvalidParameterError(); + } await _int.api.markAsRead( channelUrls: channelUrls, userId: _int.state.userId, @@ -441,8 +442,7 @@ class SendbirdSdk { createdAt > 0) { SendbirdSdk(appId: appId); - _int.sessionManager - .setUserId(_int.state.userId != null ? _int.state.userId : userId); + _int.sessionManager.setUserId(_int.state.userId ?? userId); _int.sessionManager.setSessionKey(sessionKey); await _int.api.markAsDelivered(channelUrl: channelUrl, userId: userId); } else { diff --git a/lib/services/db/memory_cache_service.dart b/lib/services/db/memory_cache_service.dart index 9999f2c0..ce3d919b 100644 --- a/lib/services/db/memory_cache_service.dart +++ b/lib/services/db/memory_cache_service.dart @@ -94,10 +94,11 @@ class ChannelCacheUnit implements CacheUnit { @override void insert(Cacheable data) { if (data is GroupChannel || data is OpenChannel) { - if (channel != null) + if (channel != null) { channel.copyWith(data); - else + } else { channel = data; + } } else if (data is ReadStatus) { final existData = readStatus[data.key]; if (existData != null) { @@ -106,10 +107,11 @@ class ChannelCacheUnit implements CacheUnit { readStatus[data.key] = data; } } else if (data is DeliveryStatus) { - if (deliveryStatus != null) + if (deliveryStatus != null) { deliveryStatus.copyWith(data); - else + } else { deliveryStatus = data; + } } else if (data is TypingStatus) { final existData = typingStatus[data.key]; if (existData != null) { diff --git a/lib/services/db/policy.dart b/lib/services/db/policy.dart index 6cf6074e..2690e297 100644 --- a/lib/services/db/policy.dart +++ b/lib/services/db/policy.dart @@ -24,7 +24,7 @@ class PeriodEviction implements EvictionPolicy { void start() { timer?.cancel(); timer = Timer(Duration(seconds: periodInSeconds), () { - this.evict(); + evict(); }); } diff --git a/lib/services/network/api_client.dart b/lib/services/network/api_client.dart index 3cd76293..d8b41a22 100644 --- a/lib/services/network/api_client.dart +++ b/lib/services/network/api_client.dart @@ -140,7 +140,7 @@ class ApiClient { GroupChannelParams params, { OnUploadProgressCallback progress, }) async { - Map body = { + final body = { 'name': params.name, 'user_ids': params.userIds, 'custom_type': params.customType, @@ -180,7 +180,7 @@ class ApiClient { GroupChannelParams params, { OnUploadProgressCallback progress, }) async { - Map body = { + final body = { 'name': params.name, 'user_ids': params.userIds, 'custom_type': params.customType, @@ -307,7 +307,7 @@ class ApiClient { channelType.urlString, channelUrl, ]); - Map body = { + final body = { 'user_id': userId, 'mark_as_read': markAsRead, }; @@ -340,11 +340,11 @@ class ApiClient { } final url = endpoint.Users.userid_groupchannel_changelogs.format([userId]); - var queryParams = Map(); + var queryParams = {}; queryParams.addAll(params.toJson()); - if (timestamp != null && timestamp > 0) + if (timestamp != null && timestamp > 0) { queryParams['change_ts'] = timestamp; - else if (token != null) queryParams['token'] = token; + } else if (token != null) queryParams['token'] = token; final res = await client.get(url: url, queryParams: queryParams); return ChannelChangeLogsResponse.fromJson(res); @@ -706,7 +706,7 @@ class ApiClient { throw InvalidParameterError(); } - if (fileSize > this.uploadSizeLimit) { + if (fileSize > uploadSizeLimit) { throw FileSizeLimitExceededError(); } @@ -719,7 +719,7 @@ class ApiClient { params.thumbnailSizes?.asMap()?.forEach((index, value) => body['thumbnail${index + 1}'] = - "${value.width.round()},${value.height.round()}"); + '${value.width.round()},${value.height.round()}'); final res = await client.multipartRequest( method: Method.post, @@ -895,8 +895,8 @@ class ApiClient { channelType.urlString, channelUrl, ]); - Map queryParams = {'include_ts': true}; - if (keys != null && keys.length > 0) { + final queryParams = {'include_ts': true}; + if (keys != null && keys.isNotEmpty) { queryParams['keys'] = keys; } final res = await client.get(url: url, queryParams: queryParams); @@ -980,8 +980,8 @@ class ApiClient { channelType.urlString, channelUrl, ]); - Map queryParams = {}; - if (keys != null && keys.length > 0) { + final queryParams = {}; + if (keys != null && keys.isNotEmpty) { queryParams['keys'] = keys; } final res = await client.get(url: url, queryParams: queryParams); @@ -1079,8 +1079,9 @@ class ApiClient { }) async { if (enable) { if (startDate == null || endDate == null) throw InvalidParameterError(); - if (endDate.difference(startDate).inSeconds < 0) + if (endDate.difference(startDate).inSeconds < 0) { throw InvalidParameterError(); + } } if (enable == null) { @@ -1219,7 +1220,7 @@ class ApiClient { @required String token, bool unique = true, }) async { - final typeString = type == PushTokenType.fcm ? "gcm" : type.asString(); + final typeString = type == PushTokenType.fcm ? 'gcm' : type.asString(); final url = endpoint.Users.userid_push_tokentype.format([ currentUserId, typeString, @@ -1236,7 +1237,7 @@ class ApiClient { } Future unregisterPushToken({PushTokenType type, String token}) async { - final typeString = type == PushTokenType.fcm ? "gcm" : type.asString(); + final typeString = type == PushTokenType.fcm ? 'gcm' : type.asString(); final url = endpoint.Users.userid_push_tokentype_token.format([ currentUserId, typeString, @@ -1563,7 +1564,7 @@ class ApiClient { }; final res = await client.get(url: url, queryParams: params); final users = - List.from(res["banned_list"]).map((e) => e['user']).toList(); + List.from(res['banned_list']).map((e) => e['user']).toList(); final output = {'users': users, 'next': res['next']}; return UserListQueryResponse.fromJson(output); } @@ -1581,7 +1582,7 @@ class ApiClient { if (token != null) 'token': token, }; final res = await client.get(url: url, queryParams: params); - final output = {'users': res["muted_list"], 'next': res['next']}; + final output = {'users': res['muted_list'], 'next': res['next']}; return UserListQueryResponse.fromJson(output); } @@ -1626,7 +1627,7 @@ class ApiClient { 'show_member_is_muted': 'true', }; final res = await client.get(url: url, queryParams: params); - final output = {'users': res["members"], 'next': res['next']}; + final output = {'users': res['members'], 'next': res['next']}; return UserListQueryResponse.fromJson(output); } @@ -1641,7 +1642,7 @@ class ApiClient { if (token != null) 'token': token, }; final res = await client.get(url: url, queryParams: params); - final output = {'users': res["participants"], 'next': res['next']}; + final output = {'users': res['participants'], 'next': res['next']}; return UserListQueryResponse.fromJson(output); } diff --git a/lib/services/network/api_endpoints.dart b/lib/services/network/api_endpoints.dart index b9a697b3..082ee286 100644 --- a/lib/services/network/api_endpoints.dart +++ b/lib/services/network/api_endpoints.dart @@ -1,14 +1,14 @@ const needleRegex = r'{#}'; const needle = '{#}'; -final RegExp exp = new RegExp(needleRegex); +final RegExp exp = RegExp(needleRegex); extension Helpers on String { String format(List args) { - Iterable matches = exp.allMatches(this); + final matches = exp.allMatches(this); assert(args.length == matches.length); var i = -1; - return this.replaceAllMapped(exp, (match) { + return replaceAllMapped(exp, (match) { i = i + 1; return '${args[i]}'; }); diff --git a/lib/services/network/http_client.dart b/lib/services/network/http_client.dart index c4d34038..c8b3d3e0 100644 --- a/lib/services/network/http_client.dart +++ b/lib/services/network/http_client.dart @@ -71,7 +71,7 @@ class HttpClient { Map queryParams, Map headers = const {}, }) async { - await ConnectionManager.readyToExecuteAPIRequest(force: this.bypassAuth); + await ConnectionManager.readyToExecuteAPIRequest(force: bypassAuth); final uri = Uri( scheme: isLocal ? 'http' : 'https', @@ -96,7 +96,7 @@ class HttpClient { Map body = const {}, Map headers = const {}, }) async { - await ConnectionManager.readyToExecuteAPIRequest(force: this.bypassAuth); + await ConnectionManager.readyToExecuteAPIRequest(force: bypassAuth); final uri = Uri( scheme: isLocal ? 'http' : 'https', @@ -121,7 +121,7 @@ class HttpClient { Map body = const {}, Map headers = const {}, }) async { - await ConnectionManager.readyToExecuteAPIRequest(force: this.bypassAuth); + await ConnectionManager.readyToExecuteAPIRequest(force: bypassAuth); final uri = Uri( scheme: isLocal ? 'http' : 'https', @@ -146,7 +146,7 @@ class HttpClient { Map body = const {}, Map headers = const {}, }) async { - await ConnectionManager.readyToExecuteAPIRequest(force: this.bypassAuth); + await ConnectionManager.readyToExecuteAPIRequest(force: bypassAuth); final uri = Uri( scheme: isLocal ? 'http' : 'https', @@ -173,7 +173,7 @@ class HttpClient { Map headers, OnUploadProgressCallback progress, }) async { - await ConnectionManager.readyToExecuteAPIRequest(force: this.bypassAuth); + await ConnectionManager.readyToExecuteAPIRequest(force: bypassAuth); final request = MultipartRequest( method.asString().toUpperCase(), @@ -243,10 +243,11 @@ class HttpClient { sessionKey = null; final result = await SendbirdSdk().getInternal().sessionManager.updateSession(); - if (result) + if (result) { throw SessionKeyRefreshSucceededError(); - else + } else { throw SessionKeyRefreshFailedError(); + } } } @@ -270,13 +271,14 @@ class HttpClient { Map _convertQueryParams(Map q) { if (q == null) return {}; - Map result = {}; + final result = {}; q.forEach((key, value) { if (value is List) { - if (value is List) + if (value is List) { result[key] = value; - else + } else { result[key] = value.map((e) => e.toString()).toList(); + } } else if (value != null) { result[key] = value.toString(); } @@ -302,8 +304,8 @@ class MultipartRequest extends http.MultipartRequest { try { var response = await client.send(this); var stream = onDone(response.stream, client.close); - return new http.StreamedResponse( - new http.ByteStream(stream), + return http.StreamedResponse( + http.ByteStream(stream), response.statusCode, contentLength: response.contentLength, request: response.request, @@ -318,20 +320,21 @@ class MultipartRequest extends http.MultipartRequest { } } - Stream onDone(Stream stream, void onDone()) => - stream.transform(new StreamTransformer.fromHandlers(handleDone: (sink) { + Stream onDone(Stream stream, void Function() onDone) => + stream.transform(StreamTransformer.fromHandlers(handleDone: (sink) { sink.close(); onDone(); })); /// Freezes all mutable fields and returns a single-subscription [ByteStream] /// that will emit the request body. + @override http.ByteStream finalize() { final byteStream = super.finalize(); if (onProgress == null) return byteStream; - final total = this.contentLength; - int bytes = 0; + final total = contentLength; + var bytes = 0; final t = StreamTransformer.fromHandlers( handleData: (List data, EventSink> sink) { diff --git a/lib/services/network/websocket_client.dart b/lib/services/network/websocket_client.dart index 4ce59b57..edeaae0c 100644 --- a/lib/services/network/websocket_client.dart +++ b/lib/services/network/websocket_client.dart @@ -6,10 +6,10 @@ import 'package:sendbird_sdk/core/models/command.dart'; import 'package:sendbird_sdk/core/models/error.dart'; import 'package:sendbird_sdk/utils/logger.dart'; -typedef void OnWSConnect(); -typedef void OnWSDisconnect(); -typedef void OnWSData(dynamic data); -typedef void OnWSError(Object error); +typedef OnWSConnect = void Function(); +typedef OnWSDisconnect = void Function(); +typedef OnWSData = void Function(dynamic data); +typedef OnWSError = void Function(Object error); class WebSocketClient { bool _connected = false; @@ -55,7 +55,7 @@ class WebSocketClient { // already conncted on same url if (_connected && url == _url) return; - var hdrs = Map(); + var hdrs = {}; hdrs['Content-Type'] = 'application/json;charset=utf8'; try { diff --git a/lib/utils/isolate/isolate_bridge_def.dart b/lib/utils/isolate/isolate_bridge_def.dart index 58e760fc..51eeb02d 100644 --- a/lib/utils/isolate/isolate_bridge_def.dart +++ b/lib/utils/isolate/isolate_bridge_def.dart @@ -12,7 +12,7 @@ enum IsoBridgeStatus { shutdown, } -typedef void IsolateBridgeEntryFunc(IsoactionInternalInit action); +typedef IsolateBridgeEntryFunc = void Function(IsoactionInternalInit action); class IsoactionInternalInit { SendPort port; diff --git a/lib/utils/isolate/isolate_bridge_master.dart b/lib/utils/isolate/isolate_bridge_master.dart index 6065bdd8..b95aa615 100644 --- a/lib/utils/isolate/isolate_bridge_master.dart +++ b/lib/utils/isolate/isolate_bridge_master.dart @@ -25,7 +25,7 @@ class IsolateMaster { _receivePortForUxIsolate = RawReceivePort(_processAction); _sendPortForExecIsolate = _receivePortForUxIsolate .sendPort; //Temporary assignment for early callers - _errors = List(); + _errors = []; _pingLastStamp = DateTime.now(); _pingCount = 0; Timer.run(initialize); @@ -46,11 +46,11 @@ class IsolateMaster { actionInit, paused: false, errorsAreFatal: false, - debugName: "Exec", + debugName: 'Exec', ); return; } catch (except) { - _setError("Exception:" + except.toString()); + _setError('Exception:' + except.toString()); } _status = IsoBridgeStatus.error; } @@ -111,9 +111,9 @@ class IsolateMaster { try { handleMessage(action); } catch (exception) { - _setError("Exception:" + + _setError('Exception:' + exception.toString() + - "-" + + '-' + action.runtimeType.toString()); } } @@ -126,13 +126,13 @@ class IsolateMaster { if (current == ref) { return current; } - if (_errors.length > 0) { + if (_errors.isNotEmpty) { return IsoBridgeStatus.error; } - int total = 0; + var total = 0; while (_status != ref) { await Future.delayed(Duration(milliseconds: 10)); - if (_errors.length > 0) { + if (_errors.isNotEmpty) { return IsoBridgeStatus.error; } total += 10; @@ -150,7 +150,7 @@ class IsolateMaster { } void handleError(String action) async { - //print("Override Handleerror:" + action); + //print('Override Handleerror:' + action); } void didInitialize() async {} diff --git a/lib/utils/isolate/isolate_bridge_slave.dart b/lib/utils/isolate/isolate_bridge_slave.dart index 56878365..bb190d98 100644 --- a/lib/utils/isolate/isolate_bridge_slave.dart +++ b/lib/utils/isolate/isolate_bridge_slave.dart @@ -51,19 +51,19 @@ class IsolateSlave { try { handleMessage(action); } catch (e) { - //print("Exec Paction Exception:" + e.toString()); - setError("Exception Thrown:" + + //print('Exec Paction Exception:' + e.toString()); + setError('Exception Thrown:' + e.toString() + - "-" + + '-' + action.runtimeType.toString()); } } // void cleanUp() async { - // throw UnimplementedError("cleanUp should be overridden"); + // throw UnimplementedError('cleanUp should be overridden'); // } void handleMessage(dynamic action) async { - throw UnimplementedError("handleMessage should be overridden"); + throw UnimplementedError('handleMessage should be overridden'); } } diff --git a/lib/utils/parsers.dart b/lib/utils/parsers.dart index aa078cc6..00f8b7ee 100644 --- a/lib/utils/parsers.dart +++ b/lib/utils/parsers.dart @@ -8,9 +8,9 @@ Future parseCommand(String data) async { } Command parseCommandData(String data) { - String cmdData = data.substring(0, 4); - String payloadData = data.substring(4); - Map payload = jsonDecode(payloadData); + final cmdData = data.substring(0, 4); + final payloadData = data.substring(4); + final payload = jsonDecode(payloadData); final cmd = Command.fromJson(payload); cmd.cmd = cmdData; cmd.payload = payload; diff --git a/pubspec.lock b/pubspec.lock index c09ae73f..e459a9cd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -430,7 +430,7 @@ packages: source: hosted version: "0.0.4+3" pedantic: - dependency: transitive + dependency: "direct dev" description: name: pedantic url: "https://pub.dartlang.org" diff --git a/pubspec.yaml b/pubspec.yaml index 544cb354..d62fc314 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: sendbird_sdk -description: Sendbird Chat SDK Dart/Flutter package +description: The Flutter SDK for Sendbird Chat brings modern messenger chat features to your iOS and Android deployments.. version: 3.0.10 homepage: https://www.sendbird.com @@ -30,4 +30,5 @@ dev_dependencies: sdk: flutter json_serializable: ^3.5.0 build_runner: ^1.0.0 - stack_trace: ^1.9.6 \ No newline at end of file + stack_trace: ^1.9.6 + pedantic: ^1.0.0 \ No newline at end of file