Merge branch 'develop' into ISSUE-1456/SendingMessageIndicatorFix
This commit is contained in:
@@ -50,7 +50,7 @@ pubspec.lock
|
||||
# If you don't generate documentation locally you can remove this line.
|
||||
doc/api/
|
||||
|
||||
# Avoid committing generated Javascript files:
|
||||
# Avoid committing generated JavaScript files:
|
||||
*.dart.js
|
||||
*.info.json # Produced by the --dump-info flag.
|
||||
*.js # When generated by dart2js. Don't specify *.js if your
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
🐞 Fixed
|
||||
|
||||
- Fixed streamWatchers. Before it was always new, now it is possible to follow the watchers of a channel.
|
||||
- Make `Message.i18n` field read-only.
|
||||
|
||||
🔄 Changed
|
||||
|
||||
- Cancelling a attachment upload now removes the attachment from the message.
|
||||
- Updated `dio` and other dependencies to resolvable versions.
|
||||
|
||||
✅ Added
|
||||
|
||||
@@ -47,7 +49,7 @@
|
||||
🛑️ Breaking Changes from `5.0.0-beta.2`
|
||||
|
||||
- `Channel.addMembers`, `Channel.removeMembers`, `Channel.inviteMembers` and `Channel.update`
|
||||
positional params are now optional params.
|
||||
positional parameters are now optional parameters.
|
||||
|
||||
```dart
|
||||
// previous
|
||||
@@ -420,21 +422,21 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
|
||||
🛑️ Breaking Changes from `1.5.3`
|
||||
|
||||
- migrate this package to null safety
|
||||
- `ConnectUserWithProvider` now requires `tokenProvider` as a required param. (Removed from the
|
||||
- `ConnectUserWithProvider` now requires `tokenProvider` as a required parameter. (Removed from the
|
||||
constructor)
|
||||
- `client.disconnect()` is now divided into two different functions
|
||||
- `client.closeConnection()` -> for closing user websocket connection.
|
||||
- `client.closeConnection()` -> for closing user web socket connection.
|
||||
- `client.disconnectUser()` -> for disconnecting user and resetting client state.
|
||||
- `client.devToken()` now returns a `Token` model instead of `String`.
|
||||
- `ApiError` is removed in favor of `StreamChatError`
|
||||
- `StreamChatError` -> parent type for all the stream errors.
|
||||
- `StreamWebSocketError` -> for user websocket related errors.
|
||||
- `StreamWebSocketError` -> for user web socket related errors.
|
||||
- `StreamChatNetworkError` -> for network related errors.
|
||||
- `client.queryChannels()`, `channel.query()` options param is removed in favor of individual params
|
||||
- `client.queryChannels()`, `channel.query()` options parameter is removed in favor of individual parameters
|
||||
- `option.state` -> bool state
|
||||
- `option.watch` -> bool watch
|
||||
- `option.presence` -> bool presence
|
||||
- `client.queryUsers()` options param is removed in favor of individual params
|
||||
- `client.queryUsers()` options parameter is removed in favor of individual parameters
|
||||
- `option.presence` -> bool presence
|
||||
- Migrate this package to null safety
|
||||
- Added typed filters
|
||||
@@ -468,28 +470,28 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
|
||||
|
||||
🛑️ Breaking Changes from `2.0.0-nullsafety.6`
|
||||
|
||||
- `ConnectUserWithProvider` now requires `tokenProvider` as a required param. (Removed from the
|
||||
- `ConnectUserWithProvider` now requires `tokenProvider` as a required parameter. (Removed from the
|
||||
constructor)
|
||||
- `client.disconnect()` is now divided into two different functions
|
||||
- `client.closeConnection()` -> for closing user websocket connection.
|
||||
- `client.closeConnection()` -> for closing user web socket connection.
|
||||
- `client.disconnectUser()` -> for disconnecting user and resetting client state.
|
||||
- `client.devToken()` now returns a `Token` model instead of `String`.
|
||||
- `ApiError` is removed in favor of `StreamChatError`
|
||||
- `StreamChatError` -> parent type for all the stream errors.
|
||||
- `StreamWebSocketError` -> for user websocket related errors.
|
||||
- `StreamWebSocketError` -> for user web socket related errors.
|
||||
- `StreamChatNetworkError` -> for network related errors.
|
||||
- `client.queryChannels()`, `channel.query()` options param is removed in favor of individual params
|
||||
- `client.queryChannels()`, `channel.query()` options parameter is removed in favor of individual parameters
|
||||
- `option.state` -> bool state
|
||||
- `option.watch` -> bool watch
|
||||
- `option.presence` -> bool presence
|
||||
- `client.queryUsers()` options param is removed in favor of individual params
|
||||
- `client.queryUsers()` options parameter is removed in favor of individual parameters
|
||||
- `option.presence` -> bool presence
|
||||
|
||||
✅ Added
|
||||
|
||||
- New `Location` enum is introduced for easily changing the client location/baseUrl.
|
||||
- New `client.openConnection()` and `client.closeConnection()` is introduced to connect/disconnect
|
||||
user ws connection.
|
||||
user WS connection.
|
||||
|
||||
🔄 Changed
|
||||
|
||||
@@ -592,7 +594,7 @@ the [V4 Migration Guide](https://getstream.io/chat/docs/sdk/flutter/guides/migra
|
||||
|
||||
- 🛑 **BREAKING** Renamed `Client` to less generic `StreamChatClient`
|
||||
- 🛑 **BREAKING** Segregated the persistence layer into separate
|
||||
package [stream_chat_persistence](https://pub.dev/packages/stream_chat_persistence)
|
||||
package [`stream_chat_persistence`](https://pub.dev/packages/stream_chat_persistence)
|
||||
- 🛑 **BREAKING** Moved `Client.backgroundKeepAlive`
|
||||
to [core package](https://pub.dev/packages/stream_chat_core)
|
||||
- 🛑 **BREAKING** Moved `Client.showLocalNotification`
|
||||
|
||||
@@ -39,7 +39,7 @@ There is a detailed Flutter example project in the `example` folder. You can dir
|
||||
|
||||
## Setup API Client
|
||||
|
||||
First you need to instantiate a chat client. The Chat client will manage API call, event handling and manage the websocket connection to Stream Chat servers. You should only create the client once and re-use it across your application.
|
||||
First you need to instantiate a chat client. The Chat client will manage API call, event handling and manage the web socket connection to Stream Chat servers. You should only create the client once and re-use it across your application.
|
||||
|
||||
```dart
|
||||
final client = StreamChatClient("stream-chat-api-key");
|
||||
@@ -47,7 +47,7 @@ final client = StreamChatClient("stream-chat-api-key");
|
||||
|
||||
### Logging
|
||||
|
||||
By default the Chat Client will write all messages with level Warn or Error to stdout.
|
||||
By default the Chat Client will write all messages with level Warn or Error to `stdout`.
|
||||
|
||||
#### Change Logging Level
|
||||
|
||||
@@ -59,7 +59,7 @@ final client = StreamChatClient("stream-chat-api-key", logLevel: Level.INFO);
|
||||
|
||||
#### Custom Logger
|
||||
|
||||
You can handle the log messages directly instead of have them written to stdout, this is very convenient if you use an error tracking tool or if you want to centralize your logs into one facility.
|
||||
You can handle the log messages directly instead of have them written to `stdout`, this is very convenient if you use an error tracking tool or if you want to centralize your logs into one facility.
|
||||
|
||||
```dart
|
||||
myLogHandlerFunction = (LogRecord record) {
|
||||
@@ -71,7 +71,7 @@ final client = StreamChatClient("stream-chat-api-key", logHandlerFunction: myLog
|
||||
|
||||
### Offline storage
|
||||
|
||||
To add data persistance you can extend the class `ChatPersistenceClient` and pass an instance to the `StreamChatClient`.
|
||||
To add data persistence, you can extend the class `ChatPersistenceClient` and pass an instance to the `StreamChatClient`.
|
||||
|
||||
```dart
|
||||
class CustomChatPersistentClient extends ChatPersistenceClient {
|
||||
@@ -84,7 +84,7 @@ final client = StreamChatClient(
|
||||
)..chatPersistenceClient = CustomChatPersistentClient();
|
||||
```
|
||||
|
||||
We provide an official persistent client in the [stream_chat_persistence](https://pub.dev/packages/stream_chat_persistence) package.
|
||||
We provide an official persistent client in the [`stream_chat_persistence`](https://pub.dev/packages/stream_chat_persistence) package.
|
||||
|
||||
```dart
|
||||
import 'package:stream_chat_persistence/stream_chat_persistence.dart';
|
||||
@@ -104,7 +104,7 @@ final client = StreamChatClient(
|
||||
|
||||
### Code conventions
|
||||
|
||||
- Make sure that you run `dartfmt` before commiting your code
|
||||
- Make sure that you run `dartfmt` before you commit your code
|
||||
- Make sure all public methods and functions are well documented
|
||||
|
||||
### Running tests
|
||||
|
||||
@@ -6,6 +6,7 @@ version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: '>=2.17.0 <3.0.0'
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
cupertino_icons: ^1.0.0
|
||||
|
||||
@@ -40,7 +40,7 @@ class SortOption<T> {
|
||||
final int direction;
|
||||
|
||||
/// Sorting field Comparator required for offline sorting
|
||||
@JsonKey(ignore: true)
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
final Comparator<T>? comparator;
|
||||
|
||||
/// Serialize model to json
|
||||
|
||||
@@ -98,8 +98,10 @@ class StreamChatNetworkError extends StreamChatError {
|
||||
}
|
||||
return StreamChatNetworkError.raw(
|
||||
code: errorResponse?.code ?? -1,
|
||||
message:
|
||||
errorResponse?.message ?? response?.statusMessage ?? error.message,
|
||||
message: errorResponse?.message ??
|
||||
response?.statusMessage ??
|
||||
error.message ??
|
||||
'',
|
||||
statusCode: errorResponse?.statusCode ?? response?.statusCode,
|
||||
data: errorResponse,
|
||||
isRequestCancelledError: error.type == DioErrorType.cancel,
|
||||
|
||||
@@ -87,8 +87,8 @@ class LoggingInterceptor extends Interceptor {
|
||||
requestHeaders['contentType'] = options.contentType?.toString();
|
||||
requestHeaders['responseType'] = options.responseType.toString();
|
||||
requestHeaders['followRedirects'] = options.followRedirects;
|
||||
requestHeaders['connectTimeout'] = options.connectTimeout;
|
||||
requestHeaders['receiveTimeout'] = options.receiveTimeout;
|
||||
requestHeaders['connectTimeout'] = options.connectTimeout?.toString();
|
||||
requestHeaders['receiveTimeout'] = options.receiveTimeout?.toString();
|
||||
_printMapAsTable(_logPrintRequest, requestHeaders, header: 'Headers');
|
||||
_printMapAsTable(_logPrintRequest, options.extra, header: 'Extras');
|
||||
}
|
||||
@@ -101,7 +101,8 @@ class LoggingInterceptor extends Interceptor {
|
||||
options.data as Map?,
|
||||
header: 'Body',
|
||||
);
|
||||
} else if (data is FormData) {
|
||||
}
|
||||
if (data is FormData) {
|
||||
final formDataMap = <String, dynamic>{}
|
||||
..addEntries(data.fields)
|
||||
..addEntries(data.files);
|
||||
@@ -121,7 +122,7 @@ class LoggingInterceptor extends Interceptor {
|
||||
@override
|
||||
void onError(DioError err, ErrorInterceptorHandler handler) {
|
||||
if (error) {
|
||||
if (err.type == DioErrorType.response) {
|
||||
if (err.type == DioErrorType.badResponse) {
|
||||
final uri = err.response?.requestOptions.uri;
|
||||
_printBoxed(
|
||||
_logPrintError,
|
||||
@@ -162,7 +163,7 @@ class LoggingInterceptor extends Interceptor {
|
||||
_logPrintResponse('║');
|
||||
_printResponse(_logPrintResponse, response);
|
||||
_logPrintResponse('║');
|
||||
_printLine(_logPrintResponse, '╚');
|
||||
_logPrintResponse('╚');
|
||||
}
|
||||
super.onResponse(response, handler);
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ class StreamHttpClient {
|
||||
httpClient = dio ?? Dio() {
|
||||
httpClient
|
||||
..options.baseUrl = _options.baseUrl
|
||||
..options.receiveTimeout = _options.receiveTimeout.inMilliseconds
|
||||
..options.connectTimeout = _options.connectTimeout.inMilliseconds
|
||||
..options.receiveTimeout = _options.receiveTimeout
|
||||
..options.connectTimeout = _options.connectTimeout
|
||||
..options.queryParameters = {
|
||||
'api_key': apiKey,
|
||||
..._options.queryParameters,
|
||||
|
||||
@@ -135,7 +135,6 @@ class Attachment extends Equatable {
|
||||
late final UploadState uploadState;
|
||||
|
||||
/// Map of custom channel extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, Object?> extraData;
|
||||
|
||||
/// The attachment ID.
|
||||
@@ -146,13 +145,13 @@ class Attachment extends Equatable {
|
||||
/// Shortcut for file size.
|
||||
///
|
||||
/// {@macro fileSize}
|
||||
@JsonKey(ignore: true)
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
int? get fileSize => extraData['file_size'] as int?;
|
||||
|
||||
/// Shortcut for file mimeType.
|
||||
///
|
||||
/// {@macro mimeType}
|
||||
@JsonKey(ignore: true)
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
String? get mimeType => extraData['mime_type'] as String?;
|
||||
|
||||
/// Known top level fields.
|
||||
|
||||
@@ -52,7 +52,7 @@ class AttachmentFile {
|
||||
|
||||
/// Byte data for this file. Particularly useful if you want to manipulate
|
||||
/// its data or easily upload to somewhere else.
|
||||
@JsonKey(ignore: true)
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
final Uint8List? bytes;
|
||||
|
||||
/// The file size in bytes.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'attachment_file.dart';
|
||||
|
||||
@@ -43,10 +43,10 @@ mixin _$UploadState {
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
TResult? Function()? preparing,
|
||||
TResult? Function(int uploaded, int total)? inProgress,
|
||||
TResult? Function()? success,
|
||||
TResult? Function(String error)? failed,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
@@ -68,10 +68,10 @@ mixin _$UploadState {
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
TResult? Function(Preparing value)? preparing,
|
||||
TResult? Function(InProgress value)? inProgress,
|
||||
TResult? Function(Success value)? success,
|
||||
TResult? Function(Failed value)? failed,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
@@ -90,16 +90,18 @@ mixin _$UploadState {
|
||||
abstract class $UploadStateCopyWith<$Res> {
|
||||
factory $UploadStateCopyWith(
|
||||
UploadState value, $Res Function(UploadState) then) =
|
||||
_$UploadStateCopyWithImpl<$Res>;
|
||||
_$UploadStateCopyWithImpl<$Res, UploadState>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$UploadStateCopyWithImpl<$Res> implements $UploadStateCopyWith<$Res> {
|
||||
class _$UploadStateCopyWithImpl<$Res, $Val extends UploadState>
|
||||
implements $UploadStateCopyWith<$Res> {
|
||||
_$UploadStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
final UploadState _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function(UploadState) _then;
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -110,14 +112,12 @@ abstract class _$$PreparingCopyWith<$Res> {
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$PreparingCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res>
|
||||
class __$$PreparingCopyWithImpl<$Res>
|
||||
extends _$UploadStateCopyWithImpl<$Res, _$Preparing>
|
||||
implements _$$PreparingCopyWith<$Res> {
|
||||
__$$PreparingCopyWithImpl(
|
||||
_$Preparing _value, $Res Function(_$Preparing) _then)
|
||||
: super(_value, (v) => _then(v as _$Preparing));
|
||||
|
||||
@override
|
||||
_$Preparing get _value => super._value as _$Preparing;
|
||||
: super(_value, _then);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -162,10 +162,10 @@ class _$Preparing extends Preparing {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
TResult? Function()? preparing,
|
||||
TResult? Function(int uploaded, int total)? inProgress,
|
||||
TResult? Function()? success,
|
||||
TResult? Function(String error)? failed,
|
||||
}) {
|
||||
return preparing?.call();
|
||||
}
|
||||
@@ -199,10 +199,10 @@ class _$Preparing extends Preparing {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
TResult? Function(Preparing value)? preparing,
|
||||
TResult? Function(InProgress value)? inProgress,
|
||||
TResult? Function(Success value)? success,
|
||||
TResult? Function(Failed value)? failed,
|
||||
}) {
|
||||
return preparing?.call(this);
|
||||
}
|
||||
@@ -242,30 +242,30 @@ abstract class _$$InProgressCopyWith<$Res> {
|
||||
factory _$$InProgressCopyWith(
|
||||
_$InProgress value, $Res Function(_$InProgress) then) =
|
||||
__$$InProgressCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({int uploaded, int total});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$InProgressCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res>
|
||||
class __$$InProgressCopyWithImpl<$Res>
|
||||
extends _$UploadStateCopyWithImpl<$Res, _$InProgress>
|
||||
implements _$$InProgressCopyWith<$Res> {
|
||||
__$$InProgressCopyWithImpl(
|
||||
_$InProgress _value, $Res Function(_$InProgress) _then)
|
||||
: super(_value, (v) => _then(v as _$InProgress));
|
||||
|
||||
@override
|
||||
_$InProgress get _value => super._value as _$InProgress;
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? uploaded = freezed,
|
||||
Object? total = freezed,
|
||||
Object? uploaded = null,
|
||||
Object? total = null,
|
||||
}) {
|
||||
return _then(_$InProgress(
|
||||
uploaded: uploaded == freezed
|
||||
uploaded: null == uploaded
|
||||
? _value.uploaded
|
||||
: uploaded // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
total: total == freezed
|
||||
total: null == total
|
||||
? _value.total
|
||||
: total // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
@@ -302,19 +302,18 @@ class _$InProgress extends InProgress {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$InProgress &&
|
||||
const DeepCollectionEquality().equals(other.uploaded, uploaded) &&
|
||||
const DeepCollectionEquality().equals(other.total, total));
|
||||
(identical(other.uploaded, uploaded) ||
|
||||
other.uploaded == uploaded) &&
|
||||
(identical(other.total, total) || other.total == total));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(uploaded),
|
||||
const DeepCollectionEquality().hash(total));
|
||||
int get hashCode => Object.hash(runtimeType, uploaded, total);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$InProgressCopyWith<_$InProgress> get copyWith =>
|
||||
__$$InProgressCopyWithImpl<_$InProgress>(this, _$identity);
|
||||
|
||||
@@ -332,10 +331,10 @@ class _$InProgress extends InProgress {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
TResult? Function()? preparing,
|
||||
TResult? Function(int uploaded, int total)? inProgress,
|
||||
TResult? Function()? success,
|
||||
TResult? Function(String error)? failed,
|
||||
}) {
|
||||
return inProgress?.call(uploaded, total);
|
||||
}
|
||||
@@ -369,10 +368,10 @@ class _$InProgress extends InProgress {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
TResult? Function(Preparing value)? preparing,
|
||||
TResult? Function(InProgress value)? inProgress,
|
||||
TResult? Function(Success value)? success,
|
||||
TResult? Function(Failed value)? failed,
|
||||
}) {
|
||||
return inProgress?.call(this);
|
||||
}
|
||||
@@ -422,13 +421,11 @@ abstract class _$$SuccessCopyWith<$Res> {
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$SuccessCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res>
|
||||
class __$$SuccessCopyWithImpl<$Res>
|
||||
extends _$UploadStateCopyWithImpl<$Res, _$Success>
|
||||
implements _$$SuccessCopyWith<$Res> {
|
||||
__$$SuccessCopyWithImpl(_$Success _value, $Res Function(_$Success) _then)
|
||||
: super(_value, (v) => _then(v as _$Success));
|
||||
|
||||
@override
|
||||
_$Success get _value => super._value as _$Success;
|
||||
: super(_value, _then);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -473,10 +470,10 @@ class _$Success extends Success {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
TResult? Function()? preparing,
|
||||
TResult? Function(int uploaded, int total)? inProgress,
|
||||
TResult? Function()? success,
|
||||
TResult? Function(String error)? failed,
|
||||
}) {
|
||||
return success?.call();
|
||||
}
|
||||
@@ -510,10 +507,10 @@ class _$Success extends Success {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
TResult? Function(Preparing value)? preparing,
|
||||
TResult? Function(InProgress value)? inProgress,
|
||||
TResult? Function(Success value)? success,
|
||||
TResult? Function(Failed value)? failed,
|
||||
}) {
|
||||
return success?.call(this);
|
||||
}
|
||||
@@ -552,24 +549,24 @@ abstract class Success extends UploadState {
|
||||
abstract class _$$FailedCopyWith<$Res> {
|
||||
factory _$$FailedCopyWith(_$Failed value, $Res Function(_$Failed) then) =
|
||||
__$$FailedCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({String error});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$FailedCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res>
|
||||
class __$$FailedCopyWithImpl<$Res>
|
||||
extends _$UploadStateCopyWithImpl<$Res, _$Failed>
|
||||
implements _$$FailedCopyWith<$Res> {
|
||||
__$$FailedCopyWithImpl(_$Failed _value, $Res Function(_$Failed) _then)
|
||||
: super(_value, (v) => _then(v as _$Failed));
|
||||
|
||||
@override
|
||||
_$Failed get _value => super._value as _$Failed;
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? error = freezed,
|
||||
Object? error = null,
|
||||
}) {
|
||||
return _then(_$Failed(
|
||||
error: error == freezed
|
||||
error: null == error
|
||||
? _value.error
|
||||
: error // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
@@ -603,16 +600,16 @@ class _$Failed extends Failed {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$Failed &&
|
||||
const DeepCollectionEquality().equals(other.error, error));
|
||||
(identical(other.error, error) || other.error == error));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(runtimeType, const DeepCollectionEquality().hash(error));
|
||||
int get hashCode => Object.hash(runtimeType, error);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$FailedCopyWith<_$Failed> get copyWith =>
|
||||
__$$FailedCopyWithImpl<_$Failed>(this, _$identity);
|
||||
|
||||
@@ -630,10 +627,10 @@ class _$Failed extends Failed {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
TResult? Function()? preparing,
|
||||
TResult? Function(int uploaded, int total)? inProgress,
|
||||
TResult? Function()? success,
|
||||
TResult? Function(String error)? failed,
|
||||
}) {
|
||||
return failed?.call(error);
|
||||
}
|
||||
@@ -667,10 +664,10 @@ class _$Failed extends Failed {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
TResult? Function(Preparing value)? preparing,
|
||||
TResult? Function(InProgress value)? inProgress,
|
||||
TResult? Function(Success value)? success,
|
||||
TResult? Function(Failed value)? failed,
|
||||
}) {
|
||||
return failed?.call(this);
|
||||
}
|
||||
|
||||
@@ -62,19 +62,19 @@ class ChannelModel {
|
||||
final String type;
|
||||
|
||||
/// The cid of this channel
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final String cid;
|
||||
|
||||
/// List of user permissions on this channel
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final List<String>? ownCapabilities;
|
||||
|
||||
/// The channel configuration data
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final ChannelConfig config;
|
||||
|
||||
/// The user that created this channel
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final User? createdBy;
|
||||
|
||||
/// True if this channel is frozen
|
||||
@@ -82,23 +82,23 @@ class ChannelModel {
|
||||
final bool frozen;
|
||||
|
||||
/// The date of the last message
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final DateTime? lastMessageAt;
|
||||
|
||||
/// The date of channel creation
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final DateTime createdAt;
|
||||
|
||||
/// The date of the last channel update
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final DateTime updatedAt;
|
||||
|
||||
/// The date of channel deletion
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final DateTime? deletedAt;
|
||||
|
||||
/// The count of this channel members
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final int memberCount;
|
||||
|
||||
/// The number of seconds in a cooldown
|
||||
@@ -106,15 +106,15 @@ class ChannelModel {
|
||||
final int cooldown;
|
||||
|
||||
/// True if the channel is disabled
|
||||
@JsonKey(ignore: true)
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
bool? get disabled => extraData['disabled'] as bool?;
|
||||
|
||||
/// True if the channel is hidden
|
||||
@JsonKey(ignore: true)
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
bool? get hidden => extraData['hidden'] as bool?;
|
||||
|
||||
/// The date of the last time channel got truncated
|
||||
@JsonKey(ignore: true)
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
DateTime? get truncatedAt {
|
||||
final truncatedAt = extraData['truncated_at'] as String?;
|
||||
if (truncatedAt == null) return null;
|
||||
@@ -122,11 +122,10 @@ class ChannelModel {
|
||||
}
|
||||
|
||||
/// Map of custom channel extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, Object?> extraData;
|
||||
|
||||
/// The team the channel belongs to
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final String? team;
|
||||
|
||||
/// Known top level fields.
|
||||
|
||||
@@ -38,30 +38,11 @@ ChannelModel _$ChannelModelFromJson(Map<String, dynamic> json) => ChannelModel(
|
||||
cooldown: json['cooldown'] as int? ?? 0,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ChannelModelToJson(ChannelModel instance) {
|
||||
final val = <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'type': instance.type,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('cid', readonly(instance.cid));
|
||||
writeNotNull('own_capabilities', readonly(instance.ownCapabilities));
|
||||
writeNotNull('config', readonly(instance.config));
|
||||
writeNotNull('created_by', readonly(instance.createdBy));
|
||||
val['frozen'] = instance.frozen;
|
||||
writeNotNull('last_message_at', readonly(instance.lastMessageAt));
|
||||
writeNotNull('created_at', readonly(instance.createdAt));
|
||||
writeNotNull('updated_at', readonly(instance.updatedAt));
|
||||
writeNotNull('deleted_at', readonly(instance.deletedAt));
|
||||
writeNotNull('member_count', readonly(instance.memberCount));
|
||||
val['cooldown'] = instance.cooldown;
|
||||
val['extra_data'] = instance.extraData;
|
||||
writeNotNull('team', readonly(instance.team));
|
||||
return val;
|
||||
}
|
||||
Map<String, dynamic> _$ChannelModelToJson(ChannelModel instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'type': instance.type,
|
||||
'frozen': instance.frozen,
|
||||
'cooldown': instance.cooldown,
|
||||
'extra_data': instance.extraData,
|
||||
};
|
||||
|
||||
@@ -95,14 +95,11 @@ class Message extends Equatable {
|
||||
final String? text;
|
||||
|
||||
/// The status of a sending message.
|
||||
@JsonKey(ignore: true)
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
final MessageSendingStatus status;
|
||||
|
||||
/// The message type.
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serializer.readOnly,
|
||||
)
|
||||
@JsonKey(includeToJson: false)
|
||||
final String type;
|
||||
|
||||
/// The list of attachments, either provided by the user or generated from a
|
||||
@@ -115,26 +112,26 @@ class Message extends Equatable {
|
||||
final List<User> mentionedUsers;
|
||||
|
||||
/// A map describing the count of number of every reaction.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final Map<String, int>? reactionCounts;
|
||||
|
||||
/// A map describing the count of score of every reaction.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final Map<String, int>? reactionScores;
|
||||
|
||||
/// The latest reactions to the message created by any user.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final List<Reaction>? latestReactions;
|
||||
|
||||
/// The reactions added to the message by the current user.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final List<Reaction>? ownReactions;
|
||||
|
||||
/// The ID of the parent message, if the message is a thread reply.
|
||||
final String? parentId;
|
||||
|
||||
/// A quoted reply message.
|
||||
@JsonKey(toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final Message? quotedMessage;
|
||||
|
||||
final String? _quotedMessageId;
|
||||
@@ -143,11 +140,11 @@ class Message extends Equatable {
|
||||
String? get quotedMessageId => _quotedMessageId ?? quotedMessage?.id;
|
||||
|
||||
/// Reserved field indicating the number of replies for this message.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final int? replyCount;
|
||||
|
||||
/// Reserved field indicating the thread participants for this message.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final List<User>? threadParticipants;
|
||||
|
||||
/// Check if this message needs to show in the channel.
|
||||
@@ -157,41 +154,38 @@ class Message extends Equatable {
|
||||
final bool silent;
|
||||
|
||||
/// If true the message is shadowed.
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serializer.readOnly,
|
||||
)
|
||||
@JsonKey(includeToJson: false)
|
||||
final bool shadowed;
|
||||
|
||||
/// A used command name.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final String? command;
|
||||
|
||||
final DateTime? _createdAt;
|
||||
|
||||
/// Reserved field indicating when the message was deleted.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final DateTime? deletedAt;
|
||||
|
||||
/// Reserved field indicating when the message was created.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
DateTime get createdAt => _createdAt ?? DateTime.now();
|
||||
|
||||
final DateTime? _updatedAt;
|
||||
|
||||
/// Reserved field indicating when the message was updated last time.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
DateTime get updatedAt => _updatedAt ?? DateTime.now();
|
||||
|
||||
/// User who sent the message.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final User? user;
|
||||
|
||||
/// If true the message is pinned.
|
||||
final bool pinned;
|
||||
|
||||
/// Reserved field indicating when the message was pinned.
|
||||
@JsonKey(toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final DateTime? pinnedAt;
|
||||
|
||||
/// Reserved field indicating when the message will expire.
|
||||
@@ -200,11 +194,10 @@ class Message extends Equatable {
|
||||
final DateTime? pinExpires;
|
||||
|
||||
/// Reserved field indicating who pinned the message.
|
||||
@JsonKey(toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final User? pinnedBy;
|
||||
|
||||
/// Message custom extraData.
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, Object?> extraData;
|
||||
|
||||
/// True if the message is a system info.
|
||||
@@ -217,7 +210,7 @@ class Message extends Equatable {
|
||||
bool get isEphemeral => type == 'ephemeral';
|
||||
|
||||
/// A Map of translations.
|
||||
@JsonKey(includeIfNull: false)
|
||||
@JsonKey(includeToJson: false)
|
||||
final Map<String, String>? i18n;
|
||||
|
||||
/// Known top level fields.
|
||||
|
||||
@@ -71,43 +71,16 @@ Message _$MessageFromJson(Map<String, dynamic> json) => Message(
|
||||
),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$MessageToJson(Message instance) {
|
||||
final val = <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'text': instance.text,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('type', readonly(instance.type));
|
||||
val['attachments'] = instance.attachments.map((e) => e.toJson()).toList();
|
||||
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));
|
||||
writeNotNull('own_reactions', readonly(instance.ownReactions));
|
||||
val['parent_id'] = instance.parentId;
|
||||
val['quoted_message'] = readonly(instance.quotedMessage);
|
||||
val['quoted_message_id'] = instance.quotedMessageId;
|
||||
writeNotNull('reply_count', readonly(instance.replyCount));
|
||||
writeNotNull('thread_participants', readonly(instance.threadParticipants));
|
||||
val['show_in_channel'] = instance.showInChannel;
|
||||
val['silent'] = instance.silent;
|
||||
writeNotNull('shadowed', readonly(instance.shadowed));
|
||||
writeNotNull('command', readonly(instance.command));
|
||||
writeNotNull('deleted_at', readonly(instance.deletedAt));
|
||||
writeNotNull('created_at', readonly(instance.createdAt));
|
||||
writeNotNull('updated_at', readonly(instance.updatedAt));
|
||||
writeNotNull('user', readonly(instance.user));
|
||||
val['pinned'] = instance.pinned;
|
||||
val['pinned_at'] = readonly(instance.pinnedAt);
|
||||
val['pin_expires'] = instance.pinExpires?.toIso8601String();
|
||||
val['pinned_by'] = readonly(instance.pinnedBy);
|
||||
val['extra_data'] = instance.extraData;
|
||||
writeNotNull('i18n', instance.i18n);
|
||||
return val;
|
||||
}
|
||||
Map<String, dynamic> _$MessageToJson(Message instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'text': instance.text,
|
||||
'attachments': instance.attachments.map((e) => e.toJson()).toList(),
|
||||
'mentioned_users': User.toIds(instance.mentionedUsers),
|
||||
'parent_id': instance.parentId,
|
||||
'quoted_message_id': instance.quotedMessageId,
|
||||
'show_in_channel': instance.showInChannel,
|
||||
'silent': instance.silent,
|
||||
'pinned': instance.pinned,
|
||||
'pin_expires': instance.pinExpires?.toIso8601String(),
|
||||
'extra_data': instance.extraData,
|
||||
};
|
||||
|
||||
@@ -33,22 +33,21 @@ class Reaction {
|
||||
final String type;
|
||||
|
||||
/// The date of the reaction
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final DateTime createdAt;
|
||||
|
||||
/// The user that sent the reaction
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final User? user;
|
||||
|
||||
/// The score of the reaction (ie. number of reactions sent)
|
||||
final int score;
|
||||
|
||||
/// The userId that sent the reaction
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final String? userId;
|
||||
|
||||
/// Reaction custom extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, Object?> extraData;
|
||||
|
||||
/// Map of custom user extraData
|
||||
|
||||
@@ -20,22 +20,9 @@ Reaction _$ReactionFromJson(Map<String, dynamic> json) => Reaction(
|
||||
extraData: json['extra_data'] as Map<String, dynamic>? ?? const {},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ReactionToJson(Reaction instance) {
|
||||
final val = <String, dynamic>{
|
||||
'message_id': instance.messageId,
|
||||
'type': instance.type,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('created_at', readonly(instance.createdAt));
|
||||
writeNotNull('user', readonly(instance.user));
|
||||
val['score'] = instance.score;
|
||||
writeNotNull('user_id', readonly(instance.userId));
|
||||
val['extra_data'] = instance.extraData;
|
||||
return val;
|
||||
}
|
||||
Map<String, dynamic> _$ReactionToJson(Reaction instance) => <String, dynamic>{
|
||||
'message_id': instance.messageId,
|
||||
'type': instance.type,
|
||||
'score': instance.score,
|
||||
'extra_data': instance.extraData,
|
||||
};
|
||||
|
||||
@@ -79,7 +79,7 @@ class User extends Equatable {
|
||||
/// Shortcut for user name.
|
||||
///
|
||||
/// {@macro name}
|
||||
@JsonKey(ignore: true)
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
String get name {
|
||||
if (extraData.containsKey('name') && extraData['name'] != null) {
|
||||
final name = extraData['name']! as String;
|
||||
@@ -91,48 +91,39 @@ class User extends Equatable {
|
||||
/// Shortcut for user image.
|
||||
///
|
||||
/// {@macro image}
|
||||
@JsonKey(ignore: true)
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
String? get image => extraData['image'] as String?;
|
||||
|
||||
/// User role.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final String? role;
|
||||
|
||||
/// User teams
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serializer.readOnly,
|
||||
)
|
||||
@JsonKey(includeToJson: false)
|
||||
final List<String> teams;
|
||||
|
||||
/// Date of user creation.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final DateTime createdAt;
|
||||
|
||||
/// Date of last user update.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final DateTime updatedAt;
|
||||
|
||||
/// Date of last user connection.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final DateTime? lastActive;
|
||||
|
||||
/// True if user is online.
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serializer.readOnly,
|
||||
)
|
||||
@JsonKey(includeToJson: false)
|
||||
final bool online;
|
||||
|
||||
/// True if user is banned from the chat.
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serializer.readOnly,
|
||||
)
|
||||
@JsonKey(includeToJson: false)
|
||||
final bool banned;
|
||||
|
||||
/// The date at which the ban will expire.
|
||||
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly)
|
||||
@JsonKey(includeToJson: false)
|
||||
final DateTime? banExpires;
|
||||
|
||||
/// The language this user prefers.
|
||||
@@ -140,7 +131,6 @@ class User extends Equatable {
|
||||
final String? language;
|
||||
|
||||
/// Map of custom user extraData.
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, Object?> extraData;
|
||||
|
||||
/// List of users to list of userIds.
|
||||
|
||||
@@ -41,14 +41,6 @@ Map<String, dynamic> _$UserToJson(User instance) {
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('role', readonly(instance.role));
|
||||
writeNotNull('teams', readonly(instance.teams));
|
||||
writeNotNull('created_at', readonly(instance.createdAt));
|
||||
writeNotNull('updated_at', readonly(instance.updatedAt));
|
||||
writeNotNull('last_active', readonly(instance.lastActive));
|
||||
writeNotNull('online', readonly(instance.online));
|
||||
writeNotNull('banned', readonly(instance.banned));
|
||||
writeNotNull('ban_expires', readonly(instance.banExpires));
|
||||
writeNotNull('language', instance.language);
|
||||
val['extra_data'] = instance.extraData;
|
||||
return val;
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
/// Used to avoid to serialize properties to json
|
||||
// ignore: prefer_void_to_null
|
||||
Null readonly(_) => null;
|
||||
|
||||
/// Helper class for serialization to and from json
|
||||
class Serializer {
|
||||
/// Used to avoid to serialize properties to json
|
||||
static const Function readOnly = readonly;
|
||||
|
||||
/// Takes unknown json keys and puts them in the `extra_data` key
|
||||
static Map<String, dynamic> moveToExtraDataFromRoot(
|
||||
Map<String, dynamic> json,
|
||||
|
||||
@@ -9,26 +9,26 @@ environment:
|
||||
sdk: '>=2.17.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
async: ^2.5.0
|
||||
collection: ^1.15.0
|
||||
dio: ^4.0.0
|
||||
equatable: ^2.0.0
|
||||
freezed_annotation: ^2.0.3
|
||||
http_parser: ^4.0.0
|
||||
jose: ^0.3.2
|
||||
json_annotation: ^4.5.0
|
||||
logging: ^1.0.1
|
||||
meta: ^1.3.0
|
||||
mime: ^1.0.0
|
||||
async: ^2.10.0
|
||||
collection: ^1.17.0
|
||||
dio: ^5.1.1
|
||||
equatable: ^2.0.5
|
||||
freezed_annotation: ^2.2.0
|
||||
http_parser: ^4.0.2
|
||||
jose: ^0.3.3
|
||||
json_annotation: ^4.8.0
|
||||
logging: ^1.1.1
|
||||
meta: ^1.8.0
|
||||
mime: ^1.0.4
|
||||
rate_limiter: ^1.0.0
|
||||
rxdart: ^0.27.0
|
||||
uuid: ^3.0.4
|
||||
web_socket_channel: ^2.0.0
|
||||
rxdart: ^0.27.7
|
||||
uuid: ^3.0.7
|
||||
web_socket_channel: ^2.3.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.0.1
|
||||
dart_code_metrics: ^4.4.0
|
||||
freezed: ^2.0.3
|
||||
json_serializable: ^6.2.0
|
||||
build_runner: ^2.3.3
|
||||
dart_code_metrics: ^5.7.0
|
||||
freezed: ^2.3.2
|
||||
json_serializable: ^6.6.1
|
||||
mocktail: ^0.3.0
|
||||
test: ^1.17.12
|
||||
test: ^1.24.1
|
||||
|
||||
+25
-101
@@ -1,4 +1,3 @@
|
||||
|
||||
{
|
||||
"channel": {
|
||||
"id": "dev",
|
||||
@@ -18,400 +17,325 @@
|
||||
"text": "fasdfa",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "dry-meadow-0-e8e74482-b4cd-48db-9d1e-30e6c191786f",
|
||||
"text": "test message",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "dry-meadow-0-53e6299f-9b97-4a9c-a27e-7e2dde49b7e0",
|
||||
"text": "test message",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "dry-meadow-0-80925be0-786e-40a5-b225-486518dafd35",
|
||||
"text": "asdfadf",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "dry-meadow-0-64d7970f-ede8-4b31-9738-1bc1756d2bfe",
|
||||
"text": "test",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "withered-cell-0-84cbd760-cf55-4f7e-9207-c5f66cccc6dc",
|
||||
"text": "hi",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "dry-meadow-0-e9203588-43c3-40b1-91f7-f217fc42aa53",
|
||||
"text": "fantastic",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "withered-cell-0-7e3552d7-7a0d-45f2-a856-e91b23a7e240",
|
||||
"text": "nice to meet you",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "dry-meadow-0-1ffeafd4-e4fc-4c84-9394-9d7cb10fff42",
|
||||
"text": "hey",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "dry-meadow-0-3f147324-12c8-4b41-9fb5-2db88d065efa",
|
||||
"text": "hello, everyone",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "dry-meadow-0-51a348ae-0c0a-44de-a556-eac7891c0cf0",
|
||||
"text": "who is there?",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "icy-recipe-7-a29e237b-8d81-4a97-9bc8-d42bca3f1356",
|
||||
"text": "하이",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "icy-recipe-7-935c396e-ddf8-4a9a-951c-0a12fa5bf055",
|
||||
"text": "what are you doing?",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "throbbing-boat-5-1e4d5730-5ff0-4d25-9948-9f34ffda43e4",
|
||||
"text": "👍",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "snowy-credit-3-3e0c1a0d-d22f-42ee-b2a1-f9f49477bf21",
|
||||
"text": "sdasas",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "snowy-credit-3-3319537e-2d0e-4876-8170-a54f046e4b7d",
|
||||
"text": "cjshsa",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "snowy-credit-3-cfaf0b46-1daa-49c5-947c-b16d6697487d",
|
||||
"text": "nhisagdhsadz",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "snowy-credit-3-cebe25a7-a3a3-49fc-9919-91c6725e81f3",
|
||||
"text": "hvadhsahzd",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "divine-glade-9-0cea9262-5766-48e9-8b22-311870aed3bf",
|
||||
"text": "hello",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "red-firefly-9-c4e9007b-bb7d-4238-ae08-5f8e3cd03d73",
|
||||
"text": "hello",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "bitter-glade-2-02aee4eb-4093-4736-808b-2de75820e854",
|
||||
"text": "hello",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "morning-sea-1-0c700bcb-46dd-4224-b590-e77bdbccc480",
|
||||
"text": "http://jaeger.ui.gtstrm.com/",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "ancient-salad-0-53e8b4e6-5b7b-43ad-aeee-8bfb6a9ed0be",
|
||||
"text": "hi",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "ancient-salad-0-8c225075-bd4c-42e2-8024-530aae13cd40",
|
||||
"text": "hi",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
},
|
||||
{
|
||||
"id": "proud-sea-7-17802096-cbf8-4e3c-addd-4ee31f4c8b5c",
|
||||
"text": "😃",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
"pin_expires": null
|
||||
}
|
||||
],
|
||||
"pinned_messages": [],
|
||||
|
||||
@@ -18,12 +18,9 @@
|
||||
],
|
||||
"mentioned_users": [],
|
||||
"parent_id": "parentId",
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null,
|
||||
"show_in_channel": true,
|
||||
"hey": "test"
|
||||
}
|
||||
@@ -394,7 +394,12 @@ void main() {
|
||||
path,
|
||||
data: {'language': language},
|
||||
)).thenAnswer((_) async => successResponse(path, data: {
|
||||
'message': translatedMessage.toJson(),
|
||||
'message': {
|
||||
...translatedMessage.toJson(),
|
||||
'i18n': {
|
||||
language: translatedMessageText,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
final res = await messageApi.translateMessage(messageId, language);
|
||||
|
||||
@@ -129,7 +129,11 @@ void main() {
|
||||
await client.get('path');
|
||||
} on StreamChatNetworkError catch (e) {
|
||||
expect(e, isA<StreamChatNetworkError>());
|
||||
expect(e.message, "Dio can't establish new connection after closed.");
|
||||
expect(
|
||||
e.message,
|
||||
"The connection errored: Dio can't establish a new connection"
|
||||
' after it was closed.',
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ pubspec.lock
|
||||
# If you don't generate documentation locally you can remove this line.
|
||||
doc/api/
|
||||
|
||||
# Avoid committing generated Javascript files:
|
||||
# Avoid committing generated JavaScript files:
|
||||
*.dart.js
|
||||
*.info.json # Produced by the --dump-info flag.
|
||||
*.js # When generated by dart2js. Don't specify *.js if your
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
- [#1456](https://github.com/GetStream/stream-chat-flutter/issues/1456) Fixed logic for showing that a message was read using sending indicator.
|
||||
- [#1462](https://github.com/GetStream/stream-chat-flutter/issues/1462) Fixed support for iPad in the share button for images.
|
||||
- [#1475](https://github.com/GetStream/stream-chat-flutter/issues/1475) Fixed typo to fix compilation.
|
||||
|
||||
✅ Added
|
||||
|
||||
@@ -12,7 +13,11 @@
|
||||
|
||||
🔄 Changed
|
||||
|
||||
- Updated `share_plus` dependency to `^6.3.0`
|
||||
- Updated dependencies to resolvable versions.
|
||||
|
||||
🚀 Improved
|
||||
-
|
||||
- Improved draw of reaction options. [#1455](https://github.com/GetStream/stream-chat-flutter/pull/1455)
|
||||
|
||||
## 5.3.0
|
||||
|
||||
@@ -82,7 +87,7 @@
|
||||
✅ Added
|
||||
|
||||
- Added `StreamMemberGridView` and `StreamMemberListView`.
|
||||
- Added support for additional text field params in `StreamMessageInput`
|
||||
- Added support for additional text field parameters in `StreamMessageInput`
|
||||
* `maxLines`
|
||||
* `minLines`
|
||||
* `textInputAction`
|
||||
@@ -267,7 +272,7 @@
|
||||
- Fix commands resetting the `StreamMessageInputController.value`.
|
||||
- [[#996]](https://github.com/GetStream/stream-chat-flutter/issues/996) Videos break bottom photo
|
||||
carousal.
|
||||
- Fix: URLs with path and/or query params are not enriched.
|
||||
- Fix: URLs with path and/or query parameters are not enriched.
|
||||
- [[#1194]](https://github.com/GetStream/stream-chat-flutter/issues/1194) Request permission to
|
||||
access gallery when opening the file picker.
|
||||
|
||||
@@ -931,11 +936,11 @@ typedef MessageBuilder = Widget Function(
|
||||
## 1.0.0-beta
|
||||
|
||||
- **Refreshed widgets design**
|
||||
- Improved api documentation
|
||||
- Improved API documentation
|
||||
- Updated `stream_chat` dependency to `^1.0.0-beta`
|
||||
- Extracted sample app into dedicated [repo](https://github.com/GetStream/flutter-samples)
|
||||
- Reimplemented existing widgets
|
||||
using [stream_chat_flutter_core](https://pub.dev/packages/stream_chat_flutter_core)
|
||||
- Extracted sample app into dedicated [repository](https://github.com/GetStream/flutter-samples)
|
||||
- Re-implemented existing widgets
|
||||
using [`stream_chat_flutter_core`](https://pub.dev/packages/stream_chat_flutter_core)
|
||||
|
||||
## 0.2.21
|
||||
|
||||
@@ -944,7 +949,7 @@ typedef MessageBuilder = Widget Function(
|
||||
|
||||
## 0.2.20+4
|
||||
|
||||
- Fix channelPreview when the message list is empty
|
||||
- Fix `channelPreview` when the message list is empty
|
||||
|
||||
## 0.2.20+3
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ It teaches you how to use this SDK and also shows how to make frequently require
|
||||
|
||||
## Example App
|
||||
|
||||
This repo includes a fully functional example app with setup instructions.
|
||||
This repository includes a fully functional example app with setup instructions.
|
||||
The example is available under the [example](https://github.com/GetStream/stream-chat-flutter/tree/master/packages/stream_chat_flutter/example) folder.
|
||||
|
||||
## Add dependency
|
||||
@@ -46,7 +46,7 @@ You should then run `flutter packages get`
|
||||
|
||||
### Android
|
||||
|
||||
The package uses [photo_manager](https://pub.dev/packages/photo_manager) to access the device's photo library.
|
||||
The package uses [`photo_manager`](https://pub.dev/packages/photo_manager) to access the device's photo library.
|
||||
Follow [this wiki](https://pub.dev/packages/photo_manager#android-10-q-29) to fulfil the Android requirements.
|
||||
You need to take additional steps if you are targeting Android 13. Read [this section](https://pub.dev/packages/photo_manager#android-13-api-33-extra-configs) for more information.
|
||||
|
||||
@@ -56,9 +56,9 @@ The library uses [flutter file picker plugin](https://github.com/miguelpruivo/fl
|
||||
files from the os.
|
||||
Follow [this wiki](https://github.com/miguelpruivo/flutter_file_picker/wiki/Setup#ios) to fulfill iOS requirements.
|
||||
|
||||
We also use [video_player](https://pub.dev/packages/video_player) to reproduce videos. Follow [this guide](https://pub.dev/packages/video_player#installation) to fulfill the requirements.
|
||||
We also use [`video_player`](https://pub.dev/packages/video_player) to reproduce videos. Follow [this guide](https://pub.dev/packages/video_player#installation) to fulfill the requirements.
|
||||
|
||||
To pick images from the camera, we use the [image_picker](https://pub.dev/packages/image_picker) plugin.
|
||||
To pick images from the camera, we use the [`image_picker`](https://pub.dev/packages/image_picker) plugin.
|
||||
Follow [these instructions](https://pub.dev/packages/image_picker#ios) to check the requirements.
|
||||
|
||||
### Web
|
||||
@@ -71,7 +71,7 @@ For the web, edit your `index.html` and add the following in the `<body>` tag in
|
||||
|
||||
### MacOS
|
||||
|
||||
For MacOS use the [file_selector](https://pub.dev/packages/file_selector#macos) package.
|
||||
For MacOS use the [`file_selector`](https://pub.dev/packages/file_selector#macos) package.
|
||||
Follow [these instructions](https://pub.dev/packages/file_selector#macos) to check the requirements.
|
||||
|
||||
You also need to add the following [entitlement](https://docs.flutter.dev/development/platform-integration/desktop#entitlements-and-the-app-sandbox):
|
||||
@@ -89,8 +89,8 @@ If it seems related to the [flutter file picker plugin](https://github.com/migue
|
||||
## Docs
|
||||
|
||||
This package provides UI components required for integrating Stream Chat into your application.
|
||||
Alternatively, you may use the core package [stream_chat_flutter_core](https://github.com/GetStream/stream-chat-flutter/tree/master/packages/stream_chat_flutter_core) which allows more customisation and provides business logic but no UI components.
|
||||
If you require the maximum amount of control over the API, please use the low level client package: [stream_chat](https://github.com/GetStream/stream-chat-flutter/tree/master/packages/stream_chat).
|
||||
Alternatively, you may use the core package [`stream_chat_flutter_core`](https://github.com/GetStream/stream-chat-flutter/tree/master/packages/stream_chat_flutter_core) which allows more customisation and provides business logic but no UI components.
|
||||
If you require the maximum amount of control over the API, please use the low level client package: [`stream_chat`](https://github.com/GetStream/stream-chat-flutter/tree/master/packages/stream_chat).
|
||||
|
||||
### UI Components
|
||||
|
||||
@@ -176,7 +176,7 @@ Out of the box, all chat widgets use their default styling, and there are two wa
|
||||
|
||||
### Offline storage
|
||||
|
||||
To add data persistance you can extend the class `ChatPersistenceClient` and pass an instance to the `StreamChatClient`.
|
||||
To add data persistence you can extend the class `ChatPersistenceClient` and pass an instance to the `StreamChatClient`.
|
||||
|
||||
```dart
|
||||
class CustomChatPersistentClient extends ChatPersistenceClient {
|
||||
@@ -208,7 +208,7 @@ final client = StreamChatClient(
|
||||
## Contributing
|
||||
|
||||
We welcome code changes that improve this library or fix a problem,
|
||||
please make sure to follow all best practices and add tests if applicable before submitting a Pull Request on Github.
|
||||
please make sure to follow all best practices and add tests if applicable before submitting a Pull Request on GitHub.
|
||||
We are pleased to merge your code into the official repository.
|
||||
Make sure to sign our [Contributor License Agreement (CLA)](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) first.
|
||||
See our license file for more details.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
@@ -199,6 +199,7 @@
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
@@ -235,6 +236,7 @@
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
|
||||
@@ -61,5 +61,7 @@
|
||||
<string>Explain why your app uses the mic</string>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -177,7 +177,7 @@ class _SplitViewState extends State<SplitView> {
|
||||
: Center(
|
||||
child: Text(
|
||||
'Pick a channel to show the messages 💬',
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -78,7 +78,7 @@ class _SplitViewState extends State<SplitView> {
|
||||
: Center(
|
||||
child: Text(
|
||||
'Pick a channel to show the messages 💬',
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -21,7 +21,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
///
|
||||
/// - We set up the Chat [StreamChatClient] with the API key
|
||||
///
|
||||
/// - We set the the current user for Chat with [StreamChatClient.connectUser]
|
||||
/// - We set the current user for Chat with [StreamChatClient.connectUser]
|
||||
/// and a pre-generated user token
|
||||
///
|
||||
/// - We make [StreamChat] the root Widget of our application
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
|
||||
#include <dart_vlc/dart_vlc_plugin.h>
|
||||
#include <desktop_drop/desktop_drop_plugin.h>
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <file_selector_linux/file_selector_plugin.h>
|
||||
#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) dart_vlc_registrar =
|
||||
@@ -20,16 +19,13 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) desktop_drop_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopDropPlugin");
|
||||
desktop_drop_plugin_register_with_registrar(desktop_drop_registrar);
|
||||
g_autoptr(FlPluginRegistrar) screen_retriever_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
|
||||
screen_retriever_plugin_register_with_registrar(screen_retriever_registrar);
|
||||
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
|
||||
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin");
|
||||
sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) window_manager_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin");
|
||||
window_manager_plugin_register_with_registrar(window_manager_registrar);
|
||||
}
|
||||
|
||||
@@ -5,10 +5,9 @@
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
dart_vlc
|
||||
desktop_drop
|
||||
screen_retriever
|
||||
file_selector_linux
|
||||
sqlite3_flutter_libs
|
||||
url_launcher_linux
|
||||
window_manager
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
@@ -203,7 +203,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 0930;
|
||||
LastUpgradeCheck = 1300;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
33CC10EC2044A3C60003C045 = {
|
||||
@@ -256,6 +256,7 @@
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3399D490228B24CF009A79C7 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
@@ -404,7 +405,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
@@ -484,7 +485,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
@@ -531,7 +532,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1000"
|
||||
LastUpgradeVersion = "1300"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -19,6 +19,7 @@ version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: '>=2.17.0 <3.0.0'
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
@@ -27,7 +28,7 @@ dependencies:
|
||||
cupertino_icons: ^1.0.4
|
||||
flutter:
|
||||
sdk: flutter
|
||||
responsive_builder: ^0.4.2
|
||||
responsive_builder: ^0.6.4
|
||||
stream_chat_flutter:
|
||||
path: ../
|
||||
stream_chat_localizations:
|
||||
|
||||
+4
-10
@@ -6,16 +6,14 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <connectivity_plus_windows/connectivity_plus_windows_plugin.h>
|
||||
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
|
||||
#include <dart_vlc/dart_vlc_plugin.h>
|
||||
#include <desktop_drop/desktop_drop_plugin.h>
|
||||
#include <file_selector_windows/file_selector_windows.h>
|
||||
#include <flutter_native_view/flutter_native_view_plugin.h>
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <share_plus/share_plus_windows_plugin_c_api.h>
|
||||
#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
|
||||
#include <thumblr_windows/thumblr_windows_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
|
||||
@@ -26,16 +24,12 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
registry->GetRegistrarForPlugin("DesktopDropPlugin"));
|
||||
FileSelectorWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
||||
FlutterNativeViewPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterNativeViewPlugin"));
|
||||
ScreenRetrieverPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
|
||||
SharePlusWindowsPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
|
||||
Sqlite3FlutterLibsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin"));
|
||||
ThumblrWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("ThumblrWindowsPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||
WindowManagerPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("WindowManagerPlugin"));
|
||||
}
|
||||
|
||||
@@ -3,16 +3,14 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
connectivity_plus_windows
|
||||
connectivity_plus
|
||||
dart_vlc
|
||||
desktop_drop
|
||||
file_selector_windows
|
||||
flutter_native_view
|
||||
screen_retriever
|
||||
share_plus
|
||||
sqlite3_flutter_libs
|
||||
thumblr_windows
|
||||
url_launcher_windows
|
||||
window_manager
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
||||
@@ -162,8 +162,8 @@ class StreamChannelHeader extends StatelessWidget
|
||||
showMessage: showConnectionStateTile && showStatus,
|
||||
message: statusString,
|
||||
child: AppBar(
|
||||
toolbarTextStyle: theme.textTheme.bodyText2,
|
||||
titleTextStyle: theme.textTheme.headline6,
|
||||
toolbarTextStyle: theme.textTheme.bodyMedium,
|
||||
titleTextStyle: theme.textTheme.titleLarge,
|
||||
systemOverlayStyle: theme.brightness == Brightness.dark
|
||||
? SystemUiOverlayStyle.light
|
||||
: SystemUiOverlayStyle.dark,
|
||||
|
||||
@@ -131,8 +131,8 @@ class StreamChannelListHeader extends StatelessWidget
|
||||
showMessage: showConnectionStateTile && showStatus,
|
||||
message: statusString,
|
||||
child: AppBar(
|
||||
toolbarTextStyle: theme.textTheme.bodyText2,
|
||||
titleTextStyle: theme.textTheme.headline6,
|
||||
toolbarTextStyle: theme.textTheme.bodyMedium,
|
||||
titleTextStyle: theme.textTheme.titleLarge,
|
||||
systemOverlayStyle: theme.brightness == Brightness.dark
|
||||
? SystemUiOverlayStyle.light
|
||||
: SystemUiOverlayStyle.dark,
|
||||
@@ -181,7 +181,10 @@ class StreamChannelListHeader extends StatelessWidget
|
||||
package: 'stream_chat_flutter',
|
||||
width: 24,
|
||||
height: 24,
|
||||
color: color,
|
||||
colorFilter: ColorFilter.mode(
|
||||
color,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -80,8 +80,8 @@ class StreamGalleryHeader extends StatelessWidget
|
||||
final galleryHeaderThemeData = StreamGalleryHeaderTheme.of(context);
|
||||
final theme = Theme.of(context);
|
||||
return AppBar(
|
||||
toolbarTextStyle: theme.textTheme.bodyText2,
|
||||
titleTextStyle: theme.textTheme.headline6,
|
||||
toolbarTextStyle: theme.textTheme.bodyMedium,
|
||||
titleTextStyle: theme.textTheme.titleLarge,
|
||||
systemOverlayStyle: theme.brightness == Brightness.dark
|
||||
? SystemUiOverlayStyle.light
|
||||
: SystemUiOverlayStyle.dark,
|
||||
|
||||
+8
-115
@@ -2,6 +2,7 @@ import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart' hide ButtonStyle;
|
||||
import 'package:stream_chat_flutter/src/message_actions_modal/mam_widgets.dart';
|
||||
import 'package:stream_chat_flutter/src/message_widget/reactions/reactions_align.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
|
||||
/// {@template messageActionsModal}
|
||||
@@ -97,34 +98,12 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
||||
|
||||
Widget _showMessageOptionsModal() {
|
||||
final mediaQueryData = MediaQuery.of(context);
|
||||
final size = mediaQueryData.size;
|
||||
final user = StreamChat.of(context).currentUser;
|
||||
final orientation = mediaQueryData.orientation;
|
||||
|
||||
final roughMaxSize = size.width * 2 / 3;
|
||||
var messageTextLength = widget.message.text!.length;
|
||||
if (widget.message.quotedMessage != null) {
|
||||
var quotedMessageLength =
|
||||
(widget.message.quotedMessage!.text?.length ?? 0) + 40;
|
||||
if (widget.message.quotedMessage!.attachments.isNotEmpty) {
|
||||
quotedMessageLength += 40;
|
||||
}
|
||||
if (quotedMessageLength > messageTextLength) {
|
||||
messageTextLength = quotedMessageLength;
|
||||
}
|
||||
}
|
||||
final roughSentenceSize = messageTextLength *
|
||||
(widget.messageTheme.messageTextStyle?.fontSize ?? 1) *
|
||||
1.2;
|
||||
final divFactor = widget.message.attachments.isNotEmpty
|
||||
? 1
|
||||
: (roughSentenceSize == 0 ? 1 : (roughSentenceSize / roughMaxSize));
|
||||
|
||||
final fontSize = widget.messageTheme.messageTextStyle?.fontSize;
|
||||
final streamChatThemeData = StreamChatTheme.of(context);
|
||||
|
||||
final numberOfReactions =
|
||||
StreamChatConfiguration.of(context).reactionIcons.length;
|
||||
final shiftFactor =
|
||||
numberOfReactions < 5 ? (5 - numberOfReactions) * 0.1 : 0.0;
|
||||
final channel = StreamChannel.of(context).channel;
|
||||
|
||||
final child = Center(
|
||||
@@ -142,11 +121,12 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
||||
builder: (context, constraints) {
|
||||
return Align(
|
||||
alignment: Alignment(
|
||||
_calculateReactionsHorizontalAlignmentValue(
|
||||
calculateReactionsHorizontalAlignment(
|
||||
user,
|
||||
divFactor,
|
||||
shiftFactor,
|
||||
widget.message,
|
||||
constraints,
|
||||
fontSize,
|
||||
orientation,
|
||||
),
|
||||
0,
|
||||
),
|
||||
@@ -156,7 +136,7 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(height: 10),
|
||||
IgnorePointer(
|
||||
child: widget.messageWidget,
|
||||
),
|
||||
@@ -281,93 +261,6 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
||||
);
|
||||
}
|
||||
|
||||
double _calculateReactionsHorizontalAlignmentValue(
|
||||
User? user,
|
||||
num divFactor,
|
||||
double shiftFactor,
|
||||
BoxConstraints constraints,
|
||||
) {
|
||||
var result = 0.0;
|
||||
var cont = true;
|
||||
if (user?.id == widget.message.user?.id) {
|
||||
if (divFactor >= 1.0) {
|
||||
// This calculation is hacky and does not cover all bases!!!
|
||||
// A better option is needed!
|
||||
|
||||
// Landscape calculations
|
||||
if (constraints.maxWidth == 1350) {
|
||||
// 12.7 iPad Pro
|
||||
result = shiftFactor + 0.5;
|
||||
cont = false;
|
||||
} else if (constraints.maxWidth == 1178) {
|
||||
// 11 inch iPad Pro
|
||||
result = shiftFactor + 0.42;
|
||||
cont = false;
|
||||
} else if (constraints.maxWidth == 1164) {
|
||||
// iPad Air 4
|
||||
result = shiftFactor + 0.4;
|
||||
cont = false;
|
||||
} else if (constraints.maxWidth == 1117) {
|
||||
// iPad Mini 6
|
||||
result = shiftFactor + 0.37;
|
||||
cont = false;
|
||||
} else if (constraints.maxWidth == 1064) {
|
||||
// iPad 9th gen
|
||||
result = shiftFactor + 0.33;
|
||||
cont = false;
|
||||
} else if (constraints.maxWidth == 1008) {
|
||||
// 9.7 inch iPad Pro
|
||||
result = shiftFactor + 0.3;
|
||||
cont = false;
|
||||
} else if (constraints.maxWidth >= 200 && constraints.maxWidth <= 400) {
|
||||
// Phone (?)
|
||||
result = shiftFactor - 0.2;
|
||||
cont = false;
|
||||
}
|
||||
|
||||
if (cont) {
|
||||
// Portrait calculations
|
||||
if (constraints.maxWidth == 1008) {
|
||||
// 12.7 iPad Pro
|
||||
result = shiftFactor + 0.3;
|
||||
} else if (constraints.maxWidth == 818) {
|
||||
// 11 inch iPad Pro
|
||||
result = shiftFactor + 0.07;
|
||||
} else if (constraints.maxWidth == 804) {
|
||||
// iPad Air 4
|
||||
result = shiftFactor + 0.04;
|
||||
} else if (constraints.maxWidth == 794) {
|
||||
// iPad 9th gen
|
||||
result = shiftFactor + 0.02;
|
||||
} else if (constraints.maxWidth >= 752) {
|
||||
// 9.7 inch iPad Pro
|
||||
result = shiftFactor - 0.05;
|
||||
} else if (constraints.maxWidth == 728) {
|
||||
// iPad Mini 6
|
||||
result = shiftFactor - 0.1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = 1.2 - divFactor;
|
||||
}
|
||||
} else {
|
||||
if (divFactor >= 1.0) {
|
||||
result = shiftFactor + 0.2;
|
||||
} else {
|
||||
result = -(1.2 - divFactor);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure reactions don't get pushed past the edge of the screen.
|
||||
//
|
||||
// Hacky!!! Needs improvement!!!
|
||||
if (result > 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
InkWell _buildCustomAction(
|
||||
BuildContext context,
|
||||
StreamMessageAction messageAction,
|
||||
|
||||
@@ -80,7 +80,6 @@ class StreamMessageTextField extends StatefulWidget {
|
||||
this.textAlignVertical,
|
||||
this.textDirection,
|
||||
this.readOnly = false,
|
||||
ToolbarOptions? toolbarOptions,
|
||||
this.showCursor,
|
||||
this.autofocus = false,
|
||||
this.obscuringCharacter = '•',
|
||||
@@ -155,31 +154,7 @@ class StreamMessageTextField extends StatefulWidget {
|
||||
keyboardType = keyboardType ??
|
||||
(maxLines == 1 ? TextInputType.text : TextInputType.multiline),
|
||||
enableInteractiveSelection =
|
||||
enableInteractiveSelection ?? (!readOnly || !obscureText),
|
||||
toolbarOptions = toolbarOptions ??
|
||||
(obscureText
|
||||
? (readOnly
|
||||
// No point in even offering "Select All" in a read-only obscured
|
||||
// field.
|
||||
? const ToolbarOptions()
|
||||
// Writable, but obscured.
|
||||
: const ToolbarOptions(
|
||||
selectAll: true,
|
||||
paste: true,
|
||||
))
|
||||
: (readOnly
|
||||
// Read-only, not obscured.
|
||||
? const ToolbarOptions(
|
||||
selectAll: true,
|
||||
copy: true,
|
||||
)
|
||||
// Writable, not obscured.
|
||||
: const ToolbarOptions(
|
||||
copy: true,
|
||||
cut: true,
|
||||
selectAll: true,
|
||||
paste: true,
|
||||
)));
|
||||
enableInteractiveSelection ?? (!readOnly || !obscureText);
|
||||
|
||||
/// Controls the message being edited.
|
||||
///
|
||||
@@ -304,13 +279,6 @@ class StreamMessageTextField extends StatefulWidget {
|
||||
/// {@macro flutter.widgets.editableText.readOnly}
|
||||
final bool readOnly;
|
||||
|
||||
/// Configuration of toolbar options.
|
||||
///
|
||||
/// If not set, select all and paste will default to be enabled. Copy and cut
|
||||
/// will be disabled if [obscureText] is true. If [readOnly] is true,
|
||||
/// paste and cut will be disabled regardless.
|
||||
final ToolbarOptions toolbarOptions;
|
||||
|
||||
/// {@macro flutter.widgets.editableText.showCursor}
|
||||
final bool? showCursor;
|
||||
|
||||
@@ -720,7 +688,6 @@ class _StreamMessageTextFieldState extends State<StreamMessageTextField>
|
||||
textAlignVertical: widget.textAlignVertical,
|
||||
textDirection: widget.textDirection,
|
||||
readOnly: widget.readOnly,
|
||||
toolbarOptions: widget.toolbarOptions,
|
||||
showCursor: widget.showCursor,
|
||||
autofocus: widget.autofocus,
|
||||
obscuringCharacter: widget.obscuringCharacter,
|
||||
|
||||
+22
-39
@@ -2,6 +2,7 @@ import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stream_chat_flutter/src/message_widget/reactions/reaction_bubble.dart';
|
||||
import 'package:stream_chat_flutter/src/message_widget/reactions/reactions_align.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
|
||||
/// {@template streamMessageReactionsModal}
|
||||
@@ -39,35 +40,13 @@ class StreamMessageReactionsModal extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final size = MediaQuery.of(context).size;
|
||||
final user = StreamChat.of(context).currentUser;
|
||||
final _userPermissions = StreamChannel.of(context).channel.ownCapabilities;
|
||||
final orientation = MediaQuery.of(context).orientation;
|
||||
|
||||
final hasReactionPermission =
|
||||
_userPermissions.contains(PermissionType.sendReaction);
|
||||
|
||||
final roughMaxSize = size.width * 2 / 3;
|
||||
var messageTextLength = message.text!.length;
|
||||
if (message.quotedMessage != null) {
|
||||
var quotedMessageLength = message.quotedMessage!.text!.length + 40;
|
||||
if (message.quotedMessage!.attachments.isNotEmpty) {
|
||||
quotedMessageLength += 40;
|
||||
}
|
||||
if (quotedMessageLength > messageTextLength) {
|
||||
messageTextLength = quotedMessageLength;
|
||||
}
|
||||
}
|
||||
final roughSentenceSize = messageTextLength *
|
||||
(messageTheme.messageTextStyle?.fontSize ?? 1) *
|
||||
1.2;
|
||||
final divFactor = message.attachments.isNotEmpty
|
||||
? 1
|
||||
: (roughSentenceSize == 0 ? 1 : (roughSentenceSize / roughMaxSize));
|
||||
|
||||
final numberOfReactions =
|
||||
StreamChatConfiguration.of(context).reactionIcons.length;
|
||||
final shiftFactor =
|
||||
numberOfReactions < 5 ? (5 - numberOfReactions) * 0.1 : 0.0;
|
||||
final fontSize = messageTheme.messageTextStyle?.fontSize;
|
||||
|
||||
final child = Center(
|
||||
child: SingleChildScrollView(
|
||||
@@ -79,22 +58,26 @@ class StreamMessageReactionsModal extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
if ((showReactions ?? hasReactionPermission) &&
|
||||
(message.status == MessageSendingStatus.sent))
|
||||
Align(
|
||||
alignment: Alignment(
|
||||
user!.id == message.user!.id
|
||||
? (divFactor >= 1.0
|
||||
? -0.2 - shiftFactor
|
||||
: (1.2 - divFactor))
|
||||
: (divFactor >= 1.0
|
||||
? shiftFactor + 0.2
|
||||
: -(1.2 - divFactor)),
|
||||
0,
|
||||
),
|
||||
child: StreamReactionPicker(
|
||||
message: message,
|
||||
),
|
||||
LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return Align(
|
||||
alignment: Alignment(
|
||||
calculateReactionsHorizontalAlignment(
|
||||
user,
|
||||
message,
|
||||
constraints,
|
||||
fontSize,
|
||||
orientation,
|
||||
),
|
||||
0,
|
||||
),
|
||||
child: StreamReactionPicker(
|
||||
message: message,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(height: 10),
|
||||
IgnorePointer(
|
||||
child: messageWidget,
|
||||
),
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
|
||||
/// This method calculates the align that the modal of reactions should have.
|
||||
/// This is an approximation based on the size of the message and the
|
||||
/// available space in the screen.
|
||||
double calculateReactionsHorizontalAlignment(
|
||||
User? user,
|
||||
Message message,
|
||||
BoxConstraints constraints,
|
||||
double? fontSize,
|
||||
Orientation orientation,
|
||||
) {
|
||||
final maxWidth = constraints.maxWidth;
|
||||
|
||||
final roughSentenceSize = message.roughMessageSize(fontSize);
|
||||
final hasAttachments = message.attachments.isNotEmpty;
|
||||
final isReply = message.quotedMessageId != null;
|
||||
final isAttachment = hasAttachments && !isReply;
|
||||
|
||||
// divFactor is the percentage of the available space that the message takes.
|
||||
// When the divFactor is bigger than 0.5 that means that the messages is
|
||||
// bigger than 50% of the available space and the modal should have an offset
|
||||
// in the direction that the message grows. When the divFactor is smaller
|
||||
// than 0.5 then the offset should be to he side opposite of the message
|
||||
// growth.
|
||||
// In resume, when divFactor > 0.5 then result > 0, when divFactor < 0.5
|
||||
// then result < 0.
|
||||
var divFactor = 0.5;
|
||||
|
||||
// When in portrait, attachments normally take 75% of the screen, when in
|
||||
// landscape, attachments normally take 50% of the screen.
|
||||
if (isAttachment) {
|
||||
if (orientation == Orientation.portrait) {
|
||||
divFactor = 0.75;
|
||||
} else {
|
||||
divFactor = 0.5;
|
||||
}
|
||||
} else {
|
||||
divFactor = roughSentenceSize == 0 ? 0.5 : (roughSentenceSize / maxWidth);
|
||||
}
|
||||
|
||||
final signal = user?.id == message.user?.id ? 1 : -1;
|
||||
final result = signal * (1 - divFactor * 2.0);
|
||||
|
||||
return _capResult(result);
|
||||
}
|
||||
|
||||
// Ensure reactions don't get pushed past the edge of the screen.
|
||||
//
|
||||
// This happens if divFactor is really big. When this happens, we can simply
|
||||
// move the model all the way to the end of screen.
|
||||
double _capResult(double result) {
|
||||
if (result > 1.0) {
|
||||
return 1;
|
||||
} else if (result < -1.0) {
|
||||
return -1;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1088,7 +1088,12 @@ class StreamSvgIcon extends StatelessWidget {
|
||||
key: key,
|
||||
width: width,
|
||||
height: height,
|
||||
color: color,
|
||||
colorFilter: color != null
|
||||
? ColorFilter.mode(
|
||||
color!,
|
||||
BlendMode.srcIn,
|
||||
)
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,8 +149,8 @@ class StreamThreadHeader extends StatelessWidget
|
||||
final theme = Theme.of(context);
|
||||
return AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
toolbarTextStyle: theme.textTheme.bodyText2,
|
||||
titleTextStyle: theme.textTheme.headline6,
|
||||
toolbarTextStyle: theme.textTheme.bodyMedium,
|
||||
titleTextStyle: theme.textTheme.titleLarge,
|
||||
systemOverlayStyle: theme.brightness == Brightness.dark
|
||||
? SystemUiOverlayStyle.light
|
||||
: SystemUiOverlayStyle.dark,
|
||||
|
||||
+1
-1
@@ -409,7 +409,7 @@ class StreamChannelListErrorWidget extends StatelessWidget {
|
||||
TextSpan(text: context.translations.loadingChannelsError),
|
||||
],
|
||||
),
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: onPressed,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:diacritic/diacritic.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@@ -12,6 +14,16 @@ extension StringExtension on String {
|
||||
String capitalize() =>
|
||||
isNotEmpty ? '${this[0].toUpperCase()}${substring(1).toLowerCase()}' : '';
|
||||
|
||||
/// Returns the biggest line of a text.
|
||||
String biggestLine() {
|
||||
if (contains('\n')) {
|
||||
return split('\n')
|
||||
.reduce((curr, next) => curr.length > next.length ? curr : next);
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the string contains only emoji's or not.
|
||||
///
|
||||
/// Emojis guidelines
|
||||
@@ -353,6 +365,33 @@ extension MessageX on Message {
|
||||
return copyWith(text: messageTextToRender);
|
||||
}
|
||||
|
||||
/// Returns an approximation of message size
|
||||
double roughMessageSize(double? fontSize) {
|
||||
var messageTextLength = min(text!.biggestLine().length, 65);
|
||||
|
||||
if (quotedMessage != null) {
|
||||
var quotedMessageLength =
|
||||
(min(quotedMessage!.text?.biggestLine().length ?? 0, 65)) + 8;
|
||||
|
||||
if (quotedMessage!.attachments.isNotEmpty) {
|
||||
quotedMessageLength += 8;
|
||||
}
|
||||
|
||||
if (quotedMessageLength > messageTextLength * 1.2) {
|
||||
messageTextLength = quotedMessageLength;
|
||||
}
|
||||
}
|
||||
|
||||
// Quoted message have a smaller font, so it is necessary to reduce the
|
||||
// size of the multiplier to count for the smaller font.
|
||||
var multiplier = 0.55;
|
||||
if (quotedMessage != null) {
|
||||
multiplier = 0.45;
|
||||
}
|
||||
|
||||
return messageTextLength * (fontSize ?? 1) * multiplier;
|
||||
}
|
||||
|
||||
/// It returns the message with the translated text if available locally
|
||||
Message translate(String language) =>
|
||||
copyWith(text: i18n?['${language}_text'] ?? text);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:stream_chat_flutter/src/video/vlc/vlc_stub.dart'
|
||||
if (dart.library.io) 'vlc_manager_desktop.dart'
|
||||
if (dar.library.html) 'vlc_manager_web.dart';
|
||||
if (dart.library.html) 'vlc_manager_web.dart';
|
||||
|
||||
/// {@template vlcManager}
|
||||
/// An abstract class for the purpose of ensuring Flutter applications that
|
||||
|
||||
@@ -12,12 +12,11 @@ environment:
|
||||
dependencies:
|
||||
cached_network_image: ^3.0.0
|
||||
chewie: ^1.3.4
|
||||
collection: ^1.15.0
|
||||
collection: ^1.17.0
|
||||
contextmenu: ^3.0.0
|
||||
dart_vlc: ^0.4.0
|
||||
desktop_drop: ^0.4.0
|
||||
diacritic: ^0.1.3
|
||||
dio: ^4.0.6
|
||||
ezanimation: ^0.6.0
|
||||
file_picker: ^5.2.4
|
||||
file_selector: ^0.9.0
|
||||
@@ -25,14 +24,13 @@ dependencies:
|
||||
sdk: flutter
|
||||
flutter_markdown: ^0.6.1
|
||||
flutter_portal: ^1.0.0
|
||||
flutter_svg: ^1.0.1
|
||||
http: ^0.13.4
|
||||
flutter_svg: ^2.0.4
|
||||
http_parser: ^4.0.0
|
||||
image_gallery_saver: ^1.7.1
|
||||
image_picker: ^0.8.2
|
||||
jiffy: ^5.0.0
|
||||
lottie: ^2.0.0
|
||||
meta: ^1.3.0
|
||||
meta: ^1.8.0
|
||||
path_provider: ^2.0.9
|
||||
photo_manager: ^2.5.2
|
||||
photo_view: ^0.14.0
|
||||
@@ -44,7 +42,7 @@ dependencies:
|
||||
thumblr: ^0.0.4
|
||||
url_launcher: ^6.1.0
|
||||
video_player: ^2.4.5
|
||||
video_player_macos: ^1.0.6
|
||||
video_player_macos: ^2.0.1
|
||||
video_thumbnail: ^0.5.0
|
||||
|
||||
flutter:
|
||||
@@ -56,9 +54,9 @@ flutter:
|
||||
uses-material-design: true
|
||||
|
||||
dev_dependencies:
|
||||
dart_code_metrics: ^4.4.0
|
||||
dart_code_metrics: ^5.7.0
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
golden_toolkit: ^0.13.0
|
||||
golden_toolkit: ^0.15.0
|
||||
mocktail: ^0.3.0
|
||||
path: ^1.8.0
|
||||
path: ^1.8.2
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## Upcoming
|
||||
|
||||
- Updated dependencies to resolvable versions.
|
||||
|
||||
## 5.3.0
|
||||
|
||||
- Updated `stream_chat` dependency to [`5.3.0`](https://pub.dev/packages/stream_chat/changelog).
|
||||
|
||||
@@ -19,6 +19,7 @@ version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: '>=2.17.0 <3.0.0'
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
@@ -27,6 +28,7 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
stream_chat_flutter_core: ^5.1.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <connectivity_plus_windows/connectivity_plus_windows_plugin.h>
|
||||
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
connectivity_plus_windows
|
||||
connectivity_plus
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
||||
@@ -83,7 +83,7 @@ abstract class PagedValueNotifier<Key, Value>
|
||||
|
||||
/// Paged value that can be used with [PagedValueNotifier].
|
||||
@freezed
|
||||
abstract class PagedValue<Key, Value> with _$PagedValue<Key, Value> {
|
||||
class PagedValue<Key, Value> with _$PagedValue<Key, Value> {
|
||||
/// Represents the success state of the [PagedValue]
|
||||
// @Assert(
|
||||
// 'nextPageKey != null',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'paged_value_notifier.dart';
|
||||
|
||||
@@ -27,11 +27,11 @@ mixin _$PagedValue<Key, Value> {
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult Function(
|
||||
TResult? Function(
|
||||
List<Value> items, Key? nextPageKey, StreamChatError? error)?
|
||||
$default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(StreamChatError error)? error,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(StreamChatError error)? error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
@@ -53,9 +53,9 @@ mixin _$PagedValue<Key, Value> {
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult Function(Success<Key, Value> value)? $default, {
|
||||
TResult Function(Loading<Key, Value> value)? loading,
|
||||
TResult Function(Error<Key, Value> value)? error,
|
||||
TResult? Function(Success<Key, Value> value)? $default, {
|
||||
TResult? Function(Loading<Key, Value> value)? loading,
|
||||
TResult? Function(Error<Key, Value> value)? error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
@@ -72,17 +72,19 @@ mixin _$PagedValue<Key, Value> {
|
||||
abstract class $PagedValueCopyWith<Key, Value, $Res> {
|
||||
factory $PagedValueCopyWith(PagedValue<Key, Value> value,
|
||||
$Res Function(PagedValue<Key, Value>) then) =
|
||||
_$PagedValueCopyWithImpl<Key, Value, $Res>;
|
||||
_$PagedValueCopyWithImpl<Key, Value, $Res, PagedValue<Key, Value>>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$PagedValueCopyWithImpl<Key, Value, $Res>
|
||||
class _$PagedValueCopyWithImpl<Key, Value, $Res,
|
||||
$Val extends PagedValue<Key, Value>>
|
||||
implements $PagedValueCopyWith<Key, Value, $Res> {
|
||||
_$PagedValueCopyWithImpl(this._value, this._then);
|
||||
|
||||
final PagedValue<Key, Value> _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function(PagedValue<Key, Value>) _then;
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -90,36 +92,35 @@ abstract class _$$SuccessCopyWith<Key, Value, $Res> {
|
||||
factory _$$SuccessCopyWith(_$Success<Key, Value> value,
|
||||
$Res Function(_$Success<Key, Value>) then) =
|
||||
__$$SuccessCopyWithImpl<Key, Value, $Res>;
|
||||
@useResult
|
||||
$Res call({List<Value> items, Key? nextPageKey, StreamChatError? error});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$SuccessCopyWithImpl<Key, Value, $Res>
|
||||
extends _$PagedValueCopyWithImpl<Key, Value, $Res>
|
||||
extends _$PagedValueCopyWithImpl<Key, Value, $Res, _$Success<Key, Value>>
|
||||
implements _$$SuccessCopyWith<Key, Value, $Res> {
|
||||
__$$SuccessCopyWithImpl(
|
||||
_$Success<Key, Value> _value, $Res Function(_$Success<Key, Value>) _then)
|
||||
: super(_value, (v) => _then(v as _$Success<Key, Value>));
|
||||
|
||||
@override
|
||||
_$Success<Key, Value> get _value => super._value as _$Success<Key, Value>;
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? items = freezed,
|
||||
Object? items = null,
|
||||
Object? nextPageKey = freezed,
|
||||
Object? error = freezed,
|
||||
}) {
|
||||
return _then(_$Success<Key, Value>(
|
||||
items: items == freezed
|
||||
items: null == items
|
||||
? _value._items
|
||||
: items // ignore: cast_nullable_to_non_nullable
|
||||
as List<Value>,
|
||||
nextPageKey: nextPageKey == freezed
|
||||
nextPageKey: freezed == nextPageKey
|
||||
? _value.nextPageKey
|
||||
: nextPageKey // ignore: cast_nullable_to_non_nullable
|
||||
as Key?,
|
||||
error: error == freezed
|
||||
error: freezed == error
|
||||
? _value.error
|
||||
: error // ignore: cast_nullable_to_non_nullable
|
||||
as StreamChatError?,
|
||||
@@ -142,6 +143,7 @@ class _$Success<Key, Value> extends Success<Key, Value>
|
||||
/// List with all items loaded so far.
|
||||
@override
|
||||
List<Value> get items {
|
||||
if (_items is EqualUnmodifiableListView) return _items;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_items);
|
||||
}
|
||||
@@ -177,7 +179,7 @@ class _$Success<Key, Value> extends Success<Key, Value>
|
||||
const DeepCollectionEquality().equals(other._items, _items) &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.nextPageKey, nextPageKey) &&
|
||||
const DeepCollectionEquality().equals(other.error, error));
|
||||
(identical(other.error, error) || other.error == error));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -185,10 +187,11 @@ class _$Success<Key, Value> extends Success<Key, Value>
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(_items),
|
||||
const DeepCollectionEquality().hash(nextPageKey),
|
||||
const DeepCollectionEquality().hash(error));
|
||||
error);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$SuccessCopyWith<Key, Value, _$Success<Key, Value>> get copyWith =>
|
||||
__$$SuccessCopyWithImpl<Key, Value, _$Success<Key, Value>>(
|
||||
this, _$identity);
|
||||
@@ -208,11 +211,11 @@ class _$Success<Key, Value> extends Success<Key, Value>
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult Function(
|
||||
TResult? Function(
|
||||
List<Value> items, Key? nextPageKey, StreamChatError? error)?
|
||||
$default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(StreamChatError error)? error,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(StreamChatError error)? error,
|
||||
}) {
|
||||
return $default?.call(items, nextPageKey, this.error);
|
||||
}
|
||||
@@ -246,9 +249,9 @@ class _$Success<Key, Value> extends Success<Key, Value>
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult Function(Success<Key, Value> value)? $default, {
|
||||
TResult Function(Loading<Key, Value> value)? loading,
|
||||
TResult Function(Error<Key, Value> value)? error,
|
||||
TResult? Function(Success<Key, Value> value)? $default, {
|
||||
TResult? Function(Loading<Key, Value> value)? loading,
|
||||
TResult? Function(Error<Key, Value> value)? error,
|
||||
}) {
|
||||
return $default?.call(this);
|
||||
}
|
||||
@@ -276,13 +279,13 @@ abstract class Success<Key, Value> extends PagedValue<Key, Value> {
|
||||
const Success._() : super._();
|
||||
|
||||
/// List with all items loaded so far.
|
||||
List<Value> get items => throw _privateConstructorUsedError;
|
||||
List<Value> get items;
|
||||
|
||||
/// The key for the next page to be fetched.
|
||||
Key? get nextPageKey => throw _privateConstructorUsedError;
|
||||
Key? get nextPageKey;
|
||||
|
||||
/// The current error, if any.
|
||||
StreamChatError? get error => throw _privateConstructorUsedError;
|
||||
StreamChatError? get error;
|
||||
@JsonKey(ignore: true)
|
||||
_$$SuccessCopyWith<Key, Value, _$Success<Key, Value>> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
@@ -297,14 +300,11 @@ abstract class _$$LoadingCopyWith<Key, Value, $Res> {
|
||||
|
||||
/// @nodoc
|
||||
class __$$LoadingCopyWithImpl<Key, Value, $Res>
|
||||
extends _$PagedValueCopyWithImpl<Key, Value, $Res>
|
||||
extends _$PagedValueCopyWithImpl<Key, Value, $Res, _$Loading<Key, Value>>
|
||||
implements _$$LoadingCopyWith<Key, Value, $Res> {
|
||||
__$$LoadingCopyWithImpl(
|
||||
_$Loading<Key, Value> _value, $Res Function(_$Loading<Key, Value>) _then)
|
||||
: super(_value, (v) => _then(v as _$Loading<Key, Value>));
|
||||
|
||||
@override
|
||||
_$Loading<Key, Value> get _value => super._value as _$Loading<Key, Value>;
|
||||
: super(_value, _then);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -349,11 +349,11 @@ class _$Loading<Key, Value> extends Loading<Key, Value>
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult Function(
|
||||
TResult? Function(
|
||||
List<Value> items, Key? nextPageKey, StreamChatError? error)?
|
||||
$default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(StreamChatError error)? error,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(StreamChatError error)? error,
|
||||
}) {
|
||||
return loading?.call();
|
||||
}
|
||||
@@ -387,9 +387,9 @@ class _$Loading<Key, Value> extends Loading<Key, Value>
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult Function(Success<Key, Value> value)? $default, {
|
||||
TResult Function(Loading<Key, Value> value)? loading,
|
||||
TResult Function(Error<Key, Value> value)? error,
|
||||
TResult? Function(Success<Key, Value> value)? $default, {
|
||||
TResult? Function(Loading<Key, Value> value)? loading,
|
||||
TResult? Function(Error<Key, Value> value)? error,
|
||||
}) {
|
||||
return loading?.call(this);
|
||||
}
|
||||
@@ -419,26 +419,25 @@ abstract class _$$ErrorCopyWith<Key, Value, $Res> {
|
||||
factory _$$ErrorCopyWith(
|
||||
_$Error<Key, Value> value, $Res Function(_$Error<Key, Value>) then) =
|
||||
__$$ErrorCopyWithImpl<Key, Value, $Res>;
|
||||
@useResult
|
||||
$Res call({StreamChatError error});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ErrorCopyWithImpl<Key, Value, $Res>
|
||||
extends _$PagedValueCopyWithImpl<Key, Value, $Res>
|
||||
extends _$PagedValueCopyWithImpl<Key, Value, $Res, _$Error<Key, Value>>
|
||||
implements _$$ErrorCopyWith<Key, Value, $Res> {
|
||||
__$$ErrorCopyWithImpl(
|
||||
_$Error<Key, Value> _value, $Res Function(_$Error<Key, Value>) _then)
|
||||
: super(_value, (v) => _then(v as _$Error<Key, Value>));
|
||||
|
||||
@override
|
||||
_$Error<Key, Value> get _value => super._value as _$Error<Key, Value>;
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? error = freezed,
|
||||
Object? error = null,
|
||||
}) {
|
||||
return _then(_$Error<Key, Value>(
|
||||
error == freezed
|
||||
null == error
|
||||
? _value.error
|
||||
: error // ignore: cast_nullable_to_non_nullable
|
||||
as StreamChatError,
|
||||
@@ -473,15 +472,15 @@ class _$Error<Key, Value> extends Error<Key, Value>
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$Error<Key, Value> &&
|
||||
const DeepCollectionEquality().equals(other.error, error));
|
||||
(identical(other.error, error) || other.error == error));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(runtimeType, const DeepCollectionEquality().hash(error));
|
||||
int get hashCode => Object.hash(runtimeType, error);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ErrorCopyWith<Key, Value, _$Error<Key, Value>> get copyWith =>
|
||||
__$$ErrorCopyWithImpl<Key, Value, _$Error<Key, Value>>(this, _$identity);
|
||||
|
||||
@@ -500,11 +499,11 @@ class _$Error<Key, Value> extends Error<Key, Value>
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult Function(
|
||||
TResult? Function(
|
||||
List<Value> items, Key? nextPageKey, StreamChatError? error)?
|
||||
$default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(StreamChatError error)? error,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(StreamChatError error)? error,
|
||||
}) {
|
||||
return error?.call(this.error);
|
||||
}
|
||||
@@ -538,9 +537,9 @@ class _$Error<Key, Value> extends Error<Key, Value>
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult Function(Success<Key, Value> value)? $default, {
|
||||
TResult Function(Loading<Key, Value> value)? loading,
|
||||
TResult Function(Error<Key, Value> value)? error,
|
||||
TResult? Function(Success<Key, Value> value)? $default, {
|
||||
TResult? Function(Loading<Key, Value> value)? loading,
|
||||
TResult? Function(Error<Key, Value> value)? error,
|
||||
}) {
|
||||
return error?.call(this);
|
||||
}
|
||||
@@ -564,7 +563,7 @@ abstract class Error<Key, Value> extends PagedValue<Key, Value> {
|
||||
const factory Error(final StreamChatError error) = _$Error<Key, Value>;
|
||||
const Error._() : super._();
|
||||
|
||||
StreamChatError get error => throw _privateConstructorUsedError;
|
||||
StreamChatError get error;
|
||||
@JsonKey(ignore: true)
|
||||
_$$ErrorCopyWith<Key, Value, _$Error<Key, Value>> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
||||
@@ -425,8 +425,8 @@ class StreamChannelState extends State<StreamChannel> {
|
||||
var message = snapshot.error.toString();
|
||||
if (snapshot.error is DioError) {
|
||||
final dioError = snapshot.error as DioError?;
|
||||
if (dioError?.type == DioErrorType.response) {
|
||||
message = dioError!.message;
|
||||
if (dioError?.type == DioErrorType.badResponse) {
|
||||
message = dioError!.message ?? 'Bad response';
|
||||
} else {
|
||||
message = 'Check your connection and retry';
|
||||
}
|
||||
|
||||
@@ -244,10 +244,11 @@ class StreamChannelListController extends PagedValueNotifier<int, Channel> {
|
||||
_unsubscribeFromChannelListEvents();
|
||||
}
|
||||
|
||||
_channelEventSubscription =
|
||||
client.on().skip(1) // Skipping the last emitted event.
|
||||
// We only need to handle the latest events.
|
||||
.listen((event) {
|
||||
_channelEventSubscription = client
|
||||
.on()
|
||||
.skip(1) // Skipping the last emitted event.
|
||||
// We only need to handle the latest events.
|
||||
.listen((event) {
|
||||
// Only handle the event if the value is in success state.
|
||||
if (value.isNotSuccess) return;
|
||||
|
||||
|
||||
@@ -10,20 +10,21 @@ environment:
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
collection: ^1.15.0
|
||||
collection: ^1.17.0
|
||||
connectivity_plus: ^3.0.2
|
||||
flutter:
|
||||
sdk: flutter
|
||||
freezed_annotation: ^2.0.3
|
||||
meta: ^1.3.0
|
||||
meta: ^1.8.0
|
||||
rxdart: ^0.27.0
|
||||
stream_chat: ^5.3.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.0.1
|
||||
dart_code_metrics: ^4.4.0
|
||||
build_runner: ^2.3.3
|
||||
dart_code_metrics: ^5.7.0
|
||||
fake_async: ^1.2.0
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
freezed: ^2.0.3
|
||||
freezed: ^2.3.2
|
||||
mocktail: ^0.3.0
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||
|
||||
Matcher isSameChannelAs(Channel targetChannel) =>
|
||||
_IsSameChannelAs(targetChannel: targetChannel);
|
||||
|
||||
class _IsSameChannelAs extends Matcher {
|
||||
const _IsSameChannelAs({
|
||||
required this.targetChannel,
|
||||
});
|
||||
|
||||
final Channel targetChannel;
|
||||
|
||||
@override
|
||||
bool matches(covariant Channel channel, Map matchState) =>
|
||||
channel.cid == targetChannel.cid;
|
||||
|
||||
@override
|
||||
Description describe(Description description) =>
|
||||
description.add('is same channel as $targetChannel');
|
||||
}
|
||||
|
||||
Matcher isSameChannelListAs(List<Channel> targetChannelList) =>
|
||||
_IsSameChannelListAs(targetChannelList: targetChannelList);
|
||||
|
||||
class _IsSameChannelListAs extends Matcher {
|
||||
const _IsSameChannelListAs({
|
||||
required this.targetChannelList,
|
||||
});
|
||||
|
||||
final List<Channel> targetChannelList;
|
||||
|
||||
@override
|
||||
bool matches(covariant List<Channel> channelList, Map matchState) {
|
||||
var matches = true;
|
||||
for (var i = 0; i < channelList.length; i++) {
|
||||
final channel = channelList[i];
|
||||
final targetChannel = targetChannelList[i];
|
||||
matches = isSameChannelAs(targetChannel).matches(channel, matchState);
|
||||
if (!matches) break;
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
@override
|
||||
Description describe(Description description) =>
|
||||
description.add('is same channelList as $targetChannelList');
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||
|
||||
Matcher isSameMessageResponseAs(GetMessageResponse targetResponse) =>
|
||||
_IsSameMessageResponseAs(targetResponse: targetResponse);
|
||||
|
||||
class _IsSameMessageResponseAs extends Matcher {
|
||||
const _IsSameMessageResponseAs({
|
||||
required this.targetResponse,
|
||||
});
|
||||
|
||||
final GetMessageResponse targetResponse;
|
||||
|
||||
@override
|
||||
bool matches(covariant GetMessageResponse response, Map matchState) =>
|
||||
response.message.id == targetResponse.message.id &&
|
||||
response.channel?.cid == targetResponse.channel?.cid;
|
||||
|
||||
@override
|
||||
Description describe(Description description) =>
|
||||
description.add('is same message response as $targetResponse');
|
||||
}
|
||||
|
||||
Matcher isSameMessageResponseListAs(
|
||||
List<GetMessageResponse> targetResponseList) =>
|
||||
_IsSameMessageResponseListAs(targetResponseList: targetResponseList);
|
||||
|
||||
class _IsSameMessageResponseListAs extends Matcher {
|
||||
const _IsSameMessageResponseListAs({
|
||||
required this.targetResponseList,
|
||||
});
|
||||
|
||||
final List<GetMessageResponse> targetResponseList;
|
||||
|
||||
@override
|
||||
bool matches(
|
||||
covariant List<GetMessageResponse> responseList, Map matchState) {
|
||||
var matches = true;
|
||||
for (var i = 0; i < responseList.length; i++) {
|
||||
final response = responseList[i];
|
||||
final targetResponse = targetResponseList[i];
|
||||
matches = isSameMessageResponseAs(targetResponse).matches(
|
||||
response,
|
||||
matchState,
|
||||
);
|
||||
if (!matches) break;
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
@override
|
||||
Description describe(Description description) =>
|
||||
description.add('is same userResponseList as $targetResponseList');
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||
|
||||
Matcher isSameMessageAs(Message targetMessage) =>
|
||||
_IsSameMessageAs(targetMessage: targetMessage);
|
||||
|
||||
class _IsSameMessageAs extends Matcher {
|
||||
const _IsSameMessageAs({
|
||||
required this.targetMessage,
|
||||
});
|
||||
|
||||
final Message targetMessage;
|
||||
|
||||
@override
|
||||
bool matches(covariant Message message, Map matchState) =>
|
||||
message.id == targetMessage.id;
|
||||
|
||||
@override
|
||||
Description describe(Description description) =>
|
||||
description.add('is same message as $targetMessage');
|
||||
}
|
||||
|
||||
Matcher isSameMessageListAs(List<Message> targetMessageList) =>
|
||||
_IsSameMessageListAs(targetMessageList: targetMessageList);
|
||||
|
||||
class _IsSameMessageListAs extends Matcher {
|
||||
const _IsSameMessageListAs({
|
||||
required this.targetMessageList,
|
||||
});
|
||||
|
||||
final List<Message> targetMessageList;
|
||||
|
||||
@override
|
||||
bool matches(covariant List<Message> messageList, Map matchState) {
|
||||
var matches = true;
|
||||
for (var i = 0; i < messageList.length; i++) {
|
||||
final message = messageList[i];
|
||||
final targetMessage = targetMessageList[i];
|
||||
matches = isSameMessageAs(targetMessage).matches(message, matchState);
|
||||
if (!matches) break;
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
@override
|
||||
Description describe(Description description) =>
|
||||
description.add('is same messageList as $targetMessageList');
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||
|
||||
Matcher isSameUserAs(User targetUser) => _IsSameUserAs(targetUser: targetUser);
|
||||
|
||||
class _IsSameUserAs extends Matcher {
|
||||
const _IsSameUserAs({
|
||||
required this.targetUser,
|
||||
});
|
||||
|
||||
final User targetUser;
|
||||
|
||||
@override
|
||||
bool matches(covariant User user, Map matchState) => user.id == targetUser.id;
|
||||
|
||||
@override
|
||||
Description describe(Description description) =>
|
||||
description.add('is same user as $targetUser');
|
||||
}
|
||||
|
||||
Matcher isSameUserListAs(List<User> targetUserList) =>
|
||||
_IsSameUserListAs(targetUserList: targetUserList);
|
||||
|
||||
class _IsSameUserListAs extends Matcher {
|
||||
const _IsSameUserListAs({
|
||||
required this.targetUserList,
|
||||
});
|
||||
|
||||
final List<User> targetUserList;
|
||||
|
||||
@override
|
||||
bool matches(covariant List<User> userList, Map matchState) {
|
||||
var matches = true;
|
||||
for (var i = 0; i < userList.length; i++) {
|
||||
final user = userList[i];
|
||||
final targetUser = targetUserList[i];
|
||||
matches = isSameUserAs(targetUser).matches(user, matchState);
|
||||
if (!matches) break;
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
@override
|
||||
Description describe(Description description) =>
|
||||
description.add('is same userList as $targetUserList');
|
||||
}
|
||||
@@ -92,9 +92,9 @@ void main() {
|
||||
|
||||
const errorMessage = 'Error! Error! Error!';
|
||||
final error = DioError(
|
||||
type: DioErrorType.response,
|
||||
error: errorMessage,
|
||||
requestOptions: RequestOptions(path: ''),
|
||||
type: DioErrorType.badResponse,
|
||||
message: errorMessage,
|
||||
requestOptions: RequestOptions(),
|
||||
);
|
||||
when(() => mockChannel.initialized)
|
||||
.thenAnswer((_) => Future.error(error));
|
||||
|
||||
@@ -15,6 +15,7 @@ dependencies:
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
stream_chat_flutter: ^5.3.0
|
||||
|
||||
dev_dependencies:
|
||||
dart_code_metrics: ^4.16.0
|
||||
flutter_test:
|
||||
|
||||
@@ -103,7 +103,7 @@ class LocalizationTrackerState extends State<LocalizationTracker> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
captionFontSize = Theme.of(context).textTheme.caption!.fontSize!;
|
||||
captionFontSize = Theme.of(context).textTheme.bodySmall!.fontSize!;
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## Upcoming
|
||||
|
||||
- Updated dependencies to resolvable versions.
|
||||
|
||||
## 5.1.0
|
||||
|
||||
- Reintroduce support for experimental indexedDB on Web.
|
||||
|
||||
@@ -6,6 +6,7 @@ version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: '>=2.17.0 <3.0.0'
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
cupertino_icons: ^1.0.3
|
||||
@@ -13,6 +14,7 @@ dependencies:
|
||||
sdk: flutter
|
||||
stream_chat: ^5.1.0
|
||||
stream_chat_persistence: ^5.1.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
@@ -10,20 +10,21 @@ environment:
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
drift: ^1.5.0
|
||||
drift: ^1.7.1
|
||||
flutter:
|
||||
sdk: flutter
|
||||
logging: ^1.0.1
|
||||
meta: ^1.3.0
|
||||
meta: ^1.8.0
|
||||
mutex: ^3.0.0
|
||||
path: ^1.8.0
|
||||
path: ^1.8.2
|
||||
path_provider: ^2.0.1
|
||||
sqlite3_flutter_libs: ^0.5.0
|
||||
stream_chat: ^5.1.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.0.1
|
||||
dart_code_metrics: ^4.4.0
|
||||
drift_dev: ^1.5.2
|
||||
build_runner: ^2.3.3
|
||||
dart_code_metrics: ^4.18.0
|
||||
drift_dev: ^1.7.1
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
mocktail: ^0.3.0
|
||||
|
||||
Reference in New Issue
Block a user