change file structure, replace rate_limit with the pub dependency
Signed-off-by: Sahil Kumar <[email protected]>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
-6
@@ -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,
|
||||
+2
-2
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user