change file structure, replace rate_limit with the pub dependency

Signed-off-by: Sahil Kumar <[email protected]>
This commit is contained in:
Sahil Kumar
2021-06-03 13:38:32 +05:30
parent eac8093b22
commit d758f3df1d
39 changed files with 126 additions and 448 deletions
@@ -1,7 +1,7 @@
import 'package:dio/dio.dart';
import 'package:stream_chat/src/core/api/responses.dart';
import 'package:stream_chat/src/core/http/stream_http_client.dart';
import 'package:stream_chat/src/extensions/string_extension.dart';
import 'package:stream_chat/src/core/util/extension.dart';
import 'package:stream_chat/src/core/models/attachment_file.dart';
/// Class responsible for uploading images and files to a given channel
@@ -1,5 +1,5 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:stream_chat/src/client.dart';
import 'package:stream_chat/src/client/client.dart';
import 'package:stream_chat/src/core/models/channel_model.dart';
import 'package:stream_chat/src/core/models/channel_state.dart';
import 'package:stream_chat/src/core/models/device.dart';
@@ -9,7 +9,7 @@ import 'package:stream_chat/src/core/models/message.dart';
import 'package:stream_chat/src/core/models/reaction.dart';
import 'package:stream_chat/src/core/models/read.dart';
import 'package:stream_chat/src/core/models/user.dart';
import 'package:stream_chat/src/errors/stream_chat_error.dart';
import 'package:stream_chat/src/core/error/error.dart';
part 'responses.g.dart';
@@ -0,0 +1,166 @@
// ignore_for_file: lines_longer_than_80_chars
import 'package:collection/collection.dart';
/// Complete list of errors that are returned by the API
/// together with the description and API code.
enum ChatErrorCode {
// Client errors
/// Unauthenticated, token not defined
undefinedToken,
// Bad Request
/// Wrong data/parameter is sent to the API
inputError,
/// Duplicate username is sent while enforce_unique_usernames is enabled
duplicateUsername,
/// Message is too long
messageTooLong,
/// Event is not supported
eventNotSupported,
/// The feature is currently disabled
/// on the dashboard (i.e. Reactions & Replies)
channelFeatureNotSupported,
/// Multiple Levels Reply is not supported
/// the API only supports 1 level deep reply threads
multipleNestling,
/// Custom Command handler returned an error
customCommandEndpointCall,
/// App config does not have custom_action_handler_url
customCommandEndpointMissing,
// Unauthorised
/// Unauthenticated, problem with authentication
authenticationError,
/// Unauthenticated, token expired
tokenExpired,
/// Unauthenticated, token date incorrect
tokenBeforeIssuedAt,
/// Unauthenticated, token not valid yet
tokenNotValid,
/// Unauthenticated, token signature invalid
tokenSignatureInvalid,
/// Access Key invalid
accessKeyError,
// Forbidden
/// Unauthorised / forbidden to make request
notAllowed,
/// App suspended
appSuspended,
/// User tried to post a message during the cooldown period
cooldownError,
// Miscellaneous
/// Resource not found
doesNotExist,
/// Request timed out
requestTimeout,
/// Payload too big
payloadTooBig,
/// Too many requests in a certain time frame
rateLimitError,
/// Request headers are too large
maximumHeaderSizeExceeded,
/// Something goes wrong in the system
internalSystemError,
/// No access to requested channels
noAccessToChannels
}
const _errorCodeWithDescription = {
ChatErrorCode.undefinedToken:
MapEntry(1000, 'Unauthorised, token not defined'),
ChatErrorCode.inputError:
MapEntry(4, 'Wrong data/parameter is sent to the API'),
ChatErrorCode.duplicateUsername: MapEntry(6,
'Duplicate username is sent while enforce_unique_usernames is enabled'),
ChatErrorCode.messageTooLong: MapEntry(20, 'Message is too long'),
ChatErrorCode.eventNotSupported: MapEntry(18, 'Event is not supported'),
ChatErrorCode.channelFeatureNotSupported: MapEntry(19,
'The feature is currently disabled on the dashboard (i.e. Reactions & Replies)'),
ChatErrorCode.multipleNestling: MapEntry(21,
'Multiple Levels Reply is not supported - the API only supports 1 level deep reply threads'),
ChatErrorCode.customCommandEndpointCall:
MapEntry(45, 'Custom Command handler returned an error'),
ChatErrorCode.customCommandEndpointMissing:
MapEntry(44, 'App config does not have custom_action_handler_url'),
ChatErrorCode.authenticationError:
MapEntry(5, 'Unauthenticated, problem with authentication'),
ChatErrorCode.tokenExpired: MapEntry(40, 'Unauthenticated, token expired'),
ChatErrorCode.tokenBeforeIssuedAt:
MapEntry(42, 'Unauthenticated, token date incorrect'),
ChatErrorCode.tokenNotValid:
MapEntry(41, 'Unauthenticated, token not valid yet'),
ChatErrorCode.tokenSignatureInvalid:
MapEntry(43, 'Unauthenticated, token signature invalid'),
ChatErrorCode.accessKeyError: MapEntry(2, 'Access Key invalid'),
ChatErrorCode.notAllowed:
MapEntry(17, 'Unauthorised / forbidden to make request'),
ChatErrorCode.appSuspended: MapEntry(99, 'App suspended'),
ChatErrorCode.cooldownError:
MapEntry(60, 'User tried to post a message during the cooldown period'),
ChatErrorCode.doesNotExist: MapEntry(16, 'Resource not found'),
ChatErrorCode.requestTimeout: MapEntry(23, 'Request timed out'),
ChatErrorCode.payloadTooBig: MapEntry(22, 'Payload too big'),
ChatErrorCode.rateLimitError:
MapEntry(9, 'Too many requests in a certain time frame'),
ChatErrorCode.maximumHeaderSizeExceeded:
MapEntry(24, 'Request headers are too large'),
ChatErrorCode.internalSystemError:
MapEntry(-1, 'Something goes wrong in the system'),
ChatErrorCode.noAccessToChannels:
MapEntry(70, 'No access to requested channels'),
};
const _authenticationErrors = [
ChatErrorCode.undefinedToken,
ChatErrorCode.authenticationError,
ChatErrorCode.tokenExpired,
ChatErrorCode.tokenBeforeIssuedAt,
ChatErrorCode.tokenNotValid,
ChatErrorCode.tokenSignatureInvalid,
ChatErrorCode.accessKeyError,
ChatErrorCode.noAccessToChannels,
];
///
ChatErrorCode? chatErrorCodeFromCode(int code) => _errorCodeWithDescription.keys
.firstWhereOrNull((key) => _errorCodeWithDescription[key]!.key == code);
///
extension ChatErrorCodeX on ChatErrorCode {
///
String get message => _errorCodeWithDescription[this]!.value;
///
int get code => _errorCodeWithDescription[this]!.key;
///
bool get isAuthenticationError => _authenticationErrors.contains(this);
}
@@ -0,0 +1,2 @@
export 'chat_error_code.dart';
export 'stream_chat_error.dart';
@@ -0,0 +1,127 @@
import 'package:equatable/equatable.dart';
import 'package:stream_chat/src/core/error/chat_error_code.dart';
import 'package:stream_chat/stream_chat.dart';
///
class StreamChatError with EquatableMixin implements Exception {
///
const StreamChatError(this.message);
/// Error message
final String message;
@override
List<Object?> get props => [message];
@override
String toString() => 'StreamChatError(message: $message)';
}
///
class StreamWebSocketError extends StreamChatError {
///
const StreamWebSocketError(
String message, {
this.data,
}) : super(message);
///
factory StreamWebSocketError.fromStreamError(Map<String, Object?> error) {
final data = ErrorResponse.fromJson(error);
final message = data.message ?? '';
return StreamWebSocketError(message, data: data);
}
///
int? get code => data?.code;
///
ChatErrorCode? get errorCode {
final code = this.code;
if (code == null) return null;
return chatErrorCodeFromCode(code);
}
/// Response body. please refer to [ErrorResponse].
final ErrorResponse? data;
@override
String toString() {
var params = 'message: $message';
if (data != null) params += ', data: $data';
return 'WebSocketError($params)';
}
}
///
class StreamChatNetworkError extends StreamChatError {
///
StreamChatNetworkError(
ChatErrorCode errorCode, {
int? statusCode,
this.data,
}) : code = errorCode.code,
statusCode = statusCode ?? data?.statusCode,
super(errorCode.message);
///
StreamChatNetworkError.raw({
required this.code,
required String message,
this.statusCode,
this.data,
}) : super(message);
///
factory StreamChatNetworkError.fromDioError(DioError error) {
final response = error.response;
ErrorResponse? errorResponse;
final data = response?.data;
if (data != null) {
errorResponse = ErrorResponse.fromJson(data);
}
return StreamChatNetworkError.raw(
code: errorResponse?.code ?? -1,
message:
errorResponse?.message ?? response?.statusMessage ?? error.message,
statusCode: errorResponse?.statusCode ?? response?.statusCode,
data: errorResponse,
)..stackTrace = error.stackTrace;
}
/// Error code
final int code;
/// HTTP status code
final int? statusCode;
/// Response body. please refer to [ErrorResponse].
final ErrorResponse? data;
StackTrace? _stackTrace;
///
set stackTrace(StackTrace? stack) => _stackTrace = stack;
///
ChatErrorCode? get errorCode => chatErrorCodeFromCode(code);
///
bool get isRetriable => data == null;
@override
List<Object?> get props => [...super.props, code, statusCode];
@override
String toString({bool printStackTrace = false}) {
var params = 'code: $code, message: $message';
if (statusCode != null) params += ', statusCode: $statusCode';
if (data != null) params += ', data: $data';
var msg = 'StreamChatNetworkError($params)';
if (printStackTrace && _stackTrace != null) {
msg += '\n$_stackTrace';
}
return msg;
}
}
@@ -5,8 +5,8 @@ import 'package:stream_chat/src/core/http/stream_http_client.dart';
import 'package:stream_chat/src/core/http/token.dart';
import 'package:stream_chat/src/core/http/token_manager.dart';
import 'package:stream_chat/src/errors/chat_error_code.dart';
import 'package:stream_chat/src/errors/stream_chat_error.dart';
import 'package:stream_chat/src/core/error/error.dart';
///
class AuthInterceptor extends Interceptor {
@@ -1,5 +1,5 @@
import 'package:dio/dio.dart';
import 'package:stream_chat/src/errors/stream_chat_error.dart';
import 'package:stream_chat/src/core/error/error.dart';
///
class StreamChatDioError extends DioError {
@@ -8,9 +8,9 @@ import 'package:stream_chat/src/core/http/interceptor/connection_id_interceptor.
import 'package:stream_chat/src/core/http/interceptor/logging_interceptor.dart';
import 'package:stream_chat/src/core/http/stream_chat_dio_error.dart';
import 'package:stream_chat/src/core/http/token_manager.dart';
import 'package:stream_chat/src/errors/stream_chat_error.dart';
import 'package:stream_chat/src/core/error/error.dart';
import 'package:stream_chat/src/location.dart';
import 'package:stream_chat/src/platform_detector/platform_detector.dart';
import 'package:stream_chat/src/core/platform_detector/platform_detector.dart';
import 'package:stream_chat/version.dart';
import 'package:stream_chat/src/core/http/connection_id_manager.dart';
@@ -3,7 +3,7 @@ import 'dart:convert';
import 'package:equatable/equatable.dart';
import 'package:jose/jose.dart';
import 'package:stream_chat/src/core/models/user.dart';
import 'package:stream_chat/src/core/utils.dart';
import 'package:stream_chat/src/core/util/utils.dart';
///
typedef GuestTokenProvider = Future<String> Function(User user);
@@ -4,7 +4,7 @@ import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:stream_chat/src/core/models/action.dart';
import 'package:stream_chat/src/core/models/attachment_file.dart';
import 'package:stream_chat/src/core/models/serialization.dart';
import 'package:stream_chat/src/core/util/serialization.dart';
import 'package:uuid/uuid.dart';
part 'attachment.g.dart';
@@ -1,6 +1,6 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:stream_chat/src/core/models/channel_config.dart';
import 'package:stream_chat/src/core/models/serialization.dart';
import 'package:stream_chat/src/core/util/serialization.dart';
import 'package:stream_chat/src/core/models/user.dart';
part 'channel_model.g.dart';
@@ -1,7 +1,7 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:stream_chat/src/core/models/channel_model.dart';
import 'package:stream_chat/src/core/models/message.dart';
import 'package:stream_chat/src/core/models/serialization.dart';
import 'package:stream_chat/src/core/util/serialization.dart';
import 'package:stream_chat/stream_chat.dart';
part 'event.g.dart';
@@ -2,7 +2,7 @@ import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:stream_chat/src/core/models/attachment.dart';
import 'package:stream_chat/src/core/models/reaction.dart';
import 'package:stream_chat/src/core/models/serialization.dart';
import 'package:stream_chat/src/core/util/serialization.dart';
import 'package:stream_chat/src/core/models/user.dart';
import 'package:uuid/uuid.dart';
@@ -112,7 +112,7 @@ class Message extends Equatable {
/// The list of user mentioned in the message
@JsonKey(
toJson: Serialization.userIds,
toJson: User.toIds,
defaultValue: [],
)
final List<User> mentionedUsers;
@@ -85,7 +85,7 @@ Map<String, dynamic> _$MessageToJson(Message instance) {
writeNotNull('type', readonly(instance.type));
val['attachments'] = instance.attachments.map((e) => e.toJson()).toList();
val['mentioned_users'] = Serialization.userIds(instance.mentionedUsers);
val['mentioned_users'] = User.toIds(instance.mentionedUsers);
writeNotNull('reaction_counts', readonly(instance.reactionCounts));
writeNotNull('reaction_scores', readonly(instance.reactionScores));
writeNotNull('latest_reactions', readonly(instance.latestReactions));
@@ -1,6 +1,6 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:stream_chat/src/core/models/channel_model.dart';
import 'package:stream_chat/src/core/models/serialization.dart';
import 'package:stream_chat/src/core/util/serialization.dart';
import 'package:stream_chat/src/core/models/user.dart';
part 'mute.g.dart';
@@ -1,7 +1,7 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:stream_chat/src/core/models/device.dart';
import 'package:stream_chat/src/core/models/mute.dart';
import 'package:stream_chat/src/core/models/serialization.dart';
import 'package:stream_chat/src/core/util/serialization.dart';
import 'package:stream_chat/src/core/models/user.dart';
part 'own_user.g.dart';
@@ -1,5 +1,5 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:stream_chat/src/core/models/serialization.dart';
import 'package:stream_chat/src/core/util/serialization.dart';
import 'package:stream_chat/src/core/models/user.dart';
part 'reaction.g.dart';
@@ -1,5 +1,5 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:stream_chat/src/core/models/serialization.dart';
import 'package:stream_chat/src/core/util/serialization.dart';
part 'user.g.dart';
@@ -92,6 +92,10 @@ class User {
return id;
}
/// List of users to list of userIds
static List<String>? toIds(List<User>? users) =>
users?.map((u) => u.id).toList();
@override
bool operator ==(Object other) =>
identical(this, other) ||
@@ -0,0 +1,78 @@
import 'package:stream_chat/src/core/platform_detector/platform_detector_stub.dart'
if (dart.library.html) 'platform_detector_web.dart'
if (dart.library.io) 'platform_detector_io.dart';
/// Possible platforms
enum PlatformType {
///
android,
///
ios,
///
web,
///
macOS,
///
windows,
///
linux,
///
fuchsia,
}
/// Utility class that provides information on the current platform
class CurrentPlatform {
CurrentPlatform._();
/// True if the app is running on android
static bool get isAndroid => type == PlatformType.android;
/// True if the app is running on ios
static bool get isIos => type == PlatformType.ios;
/// True if the app is running on web
static bool get isWeb => type == PlatformType.web;
/// True if the app is running on macos
static bool get isMacOS => type == PlatformType.macOS;
/// True if the app is running on windows
static bool get isWindows => type == PlatformType.windows;
/// True if the app is running on linux
static bool get isLinux => type == PlatformType.linux;
/// True if the app is running on fuchsia
static bool get isFuchsia => type == PlatformType.fuchsia;
/// Returns a string version of the platform
static String get name {
switch (type) {
case PlatformType.android:
return 'android';
case PlatformType.ios:
return 'ios';
case PlatformType.web:
return 'web';
case PlatformType.macOS:
return 'macos';
case PlatformType.windows:
return 'windows';
case PlatformType.linux:
return 'linux';
case PlatformType.fuchsia:
return 'fuchsia';
default:
return '';
}
}
/// Get current platform type
static PlatformType get type => currentPlatform;
}
@@ -0,0 +1,12 @@
import 'dart:io';
import 'package:stream_chat/src/core/platform_detector/platform_detector.dart';
/// Version running on native systems
PlatformType get currentPlatform {
if (Platform.isWindows) return PlatformType.windows;
if (Platform.isFuchsia) return PlatformType.fuchsia;
if (Platform.isMacOS) return PlatformType.macOS;
if (Platform.isLinux) return PlatformType.linux;
if (Platform.isIOS) return PlatformType.ios;
return PlatformType.android;
}
@@ -0,0 +1,6 @@
import 'package:stream_chat/src/core/platform_detector/platform_detector.dart';
/// Stub implementation
PlatformType get currentPlatform {
throw UnimplementedError();
}
@@ -0,0 +1,4 @@
import 'package:stream_chat/src/core/platform_detector/platform_detector.dart';
/// Version running on web
PlatformType get currentPlatform => PlatformType.web;
@@ -0,0 +1,30 @@
import 'package:http_parser/http_parser.dart';
import 'package:mime/mime.dart';
/// 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 => whereType();
}
/// Useful extension functions for [Map]
extension MapX<K, V> on Map<K, V> {
/// Returns a new map with null keys or values removed
Map<K, V> get nullProtected =>
Map.from(this)..removeWhere((key, value) => key == null || value == null);
}
/// Useful extension functions for [String]
extension StringX on String {
/// returns the mime type from the passed file name.
MediaType? get mimeType {
if (toLowerCase().endsWith('heic')) {
return MediaType.parse('image/heic');
} else {
final mimeType = lookupMimeType(this);
if (mimeType == null) return null;
return MediaType.parse(mimeType);
}
}
}
@@ -1,5 +1,3 @@
import 'package:stream_chat/src/core/models/user.dart';
/// Used to avoid to serialize properties to json
// ignore: prefer_void_to_null
Null readonly(_) => null;
@@ -9,10 +7,6 @@ class Serialization {
/// Used to avoid to serialize properties to json
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();
/// Takes unknown json keys and puts them in the `extra_data` key
static Map<String, dynamic> moveToExtraDataFromRoot(
Map<String, dynamic> json,
@@ -4,14 +4,14 @@ import 'dart:math' as math;
// This alphabet uses `A-Za-z0-9_-` symbols. The genetic algorithm helped
// optimize the gzip compression for this alphabet.
const _alphabet =
'ModuleSymbhasOwnPr0123456789ABCDEFGHNRVfgctiUvzKqYTJkLxpZXIjQW';
'ModuleSymbhasOwnPr-0123456789ABCDEFGHNRVfgctiUvz_KqYTJkLxpZXIjQW';
/// Generates a random String id
/// Adopted from: https://github.com/ai/nanoid/blob/main/non-secure/index.js
String randomId({int size = 21}) {
var id = '';
for (var i = 0; i < size; i++) {
id += _alphabet[(math.Random().nextInt(32) * 64) | 0];
id += _alphabet[(math.Random().nextDouble() * 64).floor() | 0];
}
return id;
}