Merge branch 'develop' into patch-1

This commit is contained in:
Sahil Kumar
2023-04-07 01:45:04 +05:30
committed by GitHub
82 changed files with 604 additions and 822 deletions
+14 -16
View File
@@ -1,9 +1,8 @@
name: Dart Code Metrics name: Dart Code Metrics
env: env:
flutter_version: "3.3.3" flutter_version: "3.7.0"
folders: "lib, test" folders: "lib, test"
melos_version: "2.7.1"
on: on:
pull_request: pull_request:
@@ -12,62 +11,61 @@ on:
- master - master
- develop - develop
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs: jobs:
check: check:
name: dart-code-metrics name: dart-code-metrics
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: "Git Checkout" - name: "Git Checkout"
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: "Cache Flutter dependencies"
uses: actions/cache@v2
with:
path: /opt/hostedtoolcache/flutter
key: ${{ env.flutter_version }}-flutter
- name: "Install Flutter" - name: "Install Flutter"
uses: subosito/flutter-action@v1 uses: subosito/flutter-action@v2
with: with:
cache: true
flutter-version: ${{ env.flutter_version }} flutter-version: ${{ env.flutter_version }}
- name: "Install Tools" - name: "Install Tools"
run: flutter pub global activate melos ${{ env.melos_version }} run: flutter pub global activate melos
- name: "Bootstrap Workspace" - name: "Bootstrap Workspace"
run: melos bootstrap run: melos bootstrap
- name: "Stream Chat Metrics" - name: "Stream Chat Metrics"
uses: dart-code-checker/dart-code-metrics-action@v2.0.0 uses: dart-code-checker/dart-code-metrics-action@v3
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
relative_path: 'packages/stream_chat' relative_path: 'packages/stream_chat'
folders: ${{ env.folders }} folders: ${{ env.folders }}
- name: "Stream Chat Flutter Core Metrics" - name: "Stream Chat Flutter Core Metrics"
uses: dart-code-checker/dart-code-metrics-action@v2.0.0 uses: dart-code-checker/dart-code-metrics-action@v3
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
relative_path: 'packages/stream_chat_flutter_core' relative_path: 'packages/stream_chat_flutter_core'
folders: ${{ env.folders }} folders: ${{ env.folders }}
- name: "Stream Chat Flutter Metrics" - name: "Stream Chat Flutter Metrics"
uses: dart-code-checker/dart-code-metrics-action@v2.0.0 uses: dart-code-checker/dart-code-metrics-action@v3
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
relative_path: 'packages/stream_chat_flutter' relative_path: 'packages/stream_chat_flutter'
folders: ${{ env.folders }} folders: ${{ env.folders }}
- name: "Stream Chat Localizations Metrics" - name: "Stream Chat Localizations Metrics"
uses: dart-code-checker/dart-code-metrics-action@v2.0.0 uses: dart-code-checker/dart-code-metrics-action@v3
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
relative_path: 'packages/stream_chat_localizations' relative_path: 'packages/stream_chat_localizations'
folders: ${{ env.folders }} folders: ${{ env.folders }}
- name: "Stream Chat Persistence Metrics" - name: "Stream Chat Persistence Metrics"
uses: dart-code-checker/dart-code-metrics-action@v2.0.0 uses: dart-code-checker/dart-code-metrics-action@v3
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
relative_path: 'packages/stream_chat_persistence' relative_path: 'packages/stream_chat_persistence'
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
push_docusaurus: push_docusaurus:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: push - name: push
uses: GetStream/push-stream-chat-docusaurus-action@main uses: GetStream/push-stream-chat-docusaurus-action@main
with: with:
+8 -4
View File
@@ -15,11 +15,15 @@ on:
paths-ignore: paths-ignore:
- 'docs/**' - 'docs/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs: jobs:
stream_chat: stream_chat:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: axel-op/dart-package-analyzer@v3 - uses: axel-op/dart-package-analyzer@v3
id: analysis id: analysis
with: with:
@@ -39,7 +43,7 @@ jobs:
stream_chat_persistence: stream_chat_persistence:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: axel-op/dart-package-analyzer@v3 - uses: axel-op/dart-package-analyzer@v3
id: analysis id: analysis
with: with:
@@ -60,7 +64,7 @@ jobs:
stream_chat_flutter_core: stream_chat_flutter_core:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: axel-op/dart-package-analyzer@v3 - uses: axel-op/dart-package-analyzer@v3
id: analysis id: analysis
with: with:
@@ -80,7 +84,7 @@ jobs:
stream_chat_flutter: stream_chat_flutter:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: axel-op/dart-package-analyzer@v3 - uses: axel-op/dart-package-analyzer@v3
id: analysis id: analysis
with: with:
+4
View File
@@ -8,6 +8,10 @@ on:
branches: branches:
- develop - develop
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs: jobs:
conventional_pr_title: conventional_pr_title:
runs-on: ubuntu-latest runs-on: ubuntu-latest
+18 -27
View File
@@ -2,8 +2,7 @@ name: stream_flutter_workflow
env: env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'
flutter_version: "3.3.3" flutter_version: "3.7.0"
melos_version: "2.7.1"
on: on:
pull_request: pull_request:
@@ -13,6 +12,10 @@ on:
- master - master
- develop - develop
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs: jobs:
analyze: analyze:
timeout-minutes: 15 timeout-minutes: 15
@@ -20,21 +23,17 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: "Git Checkout" - name: "Git Checkout"
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Cache Flutter dependencies
uses: actions/cache@v2
with:
path: /opt/hostedtoolcache/flutter
key: ${{ env.flutter_version }}-flutter
- name: "Install Flutter" - name: "Install Flutter"
uses: subosito/flutter-action@v1 uses: subosito/flutter-action@v2
with: with:
cache: true
flutter-version: ${{ env.flutter_version }} flutter-version: ${{ env.flutter_version }}
- name: "Install Tools" - name: "Install Tools"
run: | run: |
flutter pub global activate melos ${{ env.melos_version }} flutter pub global activate melos
- name: "Bootstrap Workspace" - name: "Bootstrap Workspace"
run: melos bootstrap --verbose run: melos bootstrap --verbose
- name: "Dart Analyze" - name: "Dart Analyze"
@@ -51,21 +50,17 @@ jobs:
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- name: "Git Checkout" - name: "Git Checkout"
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Cache Flutter dependencies
uses: actions/cache@v2
with:
path: /opt/hostedtoolcache/flutter
key: ${{ env.flutter_version }}-flutter
- name: "Install Flutter" - name: "Install Flutter"
uses: subosito/flutter-action@v1 uses: subosito/flutter-action@v2
with: with:
cache: true
flutter-version: ${{ env.flutter_version }} flutter-version: ${{ env.flutter_version }}
- name: "Install Tools" - name: "Install Tools"
run: | run: |
flutter pub global activate melos ${{ env.melos_version }} flutter pub global activate melos
- name: "Bootstrap Workspace" - name: "Bootstrap Workspace"
run: melos bootstrap run: melos bootstrap
- name: "Melos Format" - name: "Melos Format"
@@ -75,26 +70,22 @@ jobs:
./.github/workflows/scripts/validate-formatting.sh ./.github/workflows/scripts/validate-formatting.sh
test: test:
runs-on: macos-latest runs-on: ubuntu-latest
if: github.event.pull_request.draft == false if: github.event.pull_request.draft == false
timeout-minutes: 30 timeout-minutes: 30
steps: steps:
- name: "Git Checkout" - name: "Git Checkout"
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Cache Flutter dependencies
uses: actions/cache@v2
with:
path: /Users/runner/hostedtoolcache/flutter
key: ${{ env.flutter_version }}-flutter
- name: "Install Flutter" - name: "Install Flutter"
uses: subosito/flutter-action@v1 uses: subosito/flutter-action@v2
with: with:
cache: true
flutter-version: ${{ env.flutter_version }} flutter-version: ${{ env.flutter_version }}
- name: "Install Tools" - name: "Install Tools"
run: | run: |
flutter pub global activate melos ${{ env.melos_version }} flutter pub global activate melos
flutter pub global activate remove_from_coverage flutter pub global activate remove_from_coverage
- name: "Bootstrap Workspace" - name: "Bootstrap Workspace"
run: melos bootstrap run: melos bootstrap
@@ -14,7 +14,7 @@ Before investigating potential solutions, lets first take a look at the relev
Most of the Stream Chat Flutter UI widgets rely on having a [StreamChat](../../customization/stream_chat_and_theming/) ancestor in the widget tree. Most of the Stream Chat Flutter UI widgets rely on having a [StreamChat](../../customization/stream_chat_and_theming/) ancestor in the widget tree.
The **StreamChat** widget is an [InheritedWidget](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html) that exposes the **StreamChatClient** through **BuildContext**. The **StreamChat** widget is an [InheritedWidget](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html) that exposes the **StreamChatClient** through **BuildContext**.
This widget also initializes the [StreamChatCore](../../stream_chat_flutter_core/stream_chat_core.mdx) widget and the **StreamChatTheme**. This widget also initializes the [StreamChatCore](../04-stream_chat_flutter_core/stream_chat_core.mdx) widget and the **StreamChatTheme**.
**StreamChatCore** is a **StatefulWidget** used to react to life cycle changes and system updates. **StreamChatCore** is a **StatefulWidget** used to react to life cycle changes and system updates.
When the app goes into the background, the WebSocket connection is closed. When the app goes into the background, the WebSocket connection is closed.
+9 -9
View File
@@ -51,11 +51,11 @@ scripts:
description: Build all generated files for Dart & Flutter packages in this project. description: Build all generated files for Dart & Flutter packages in this project.
generate:dart: generate:dart:
run: melos exec -c 1 --depends-on="build_runner" --no-flutter -- "dart run build_runner build --delete-conflicting-outputs --enable-experiment=super-parameters,enhanced-enums" run: melos exec -c 1 --depends-on="build_runner" --no-flutter -- "dart run build_runner build --delete-conflicting-outputs"
description: Build all generated files for Dart packages in this project. description: Build all generated files for Dart packages in this project.
generate:flutter: generate:flutter:
run: melos exec -c 1 --depends-on="build_runner" --flutter -- "flutter run build_runner build --delete-conflicting-outputs --enable-experiment=super-parameters,enhanced-enums" run: melos exec -c 1 --depends-on="build_runner" --flutter -- "flutter pub run build_runner build --delete-conflicting-outputs"
description: Build all generated files for Flutter packages in this project. description: Build all generated files for Flutter packages in this project.
test:all: test:all:
@@ -65,29 +65,29 @@ scripts:
test:dart: test:dart:
run: melos exec -c 1 --fail-fast -- "flutter test --coverage" run: melos exec -c 1 --fail-fast -- "flutter test --coverage"
description: Run Dart tests for a specific package in this project. description: Run Dart tests for a specific package in this project.
select-package: packageFilters:
flutter: false flutter: false
dir-exists: test dirExists: test
test:flutter: test:flutter:
run: melos exec -c 4 --fail-fast -- "flutter test --coverage" run: melos exec -c 4 --fail-fast -- "flutter test --coverage"
description: Run Flutter tests for a specific package in this project. description: Run Flutter tests for a specific package in this project.
select-package: packageFilters:
flutter: true flutter: true
dir-exists: test dirExists: test
clean:flutter: clean:flutter:
run: melos exec -c 4 --fail-fast -- "flutter clean" run: melos exec -c 4 --fail-fast -- "flutter clean"
description: Run Flutter clean for a specific package in this project. description: Run Flutter clean for a specific package in this project.
select-package: packageFilters:
flutter: true flutter: true
coverage:ignore-file: coverage:ignore-file:
run: | run: |
melos exec -c 5 --fail-fast -- "\$MELOS_ROOT_PATH/.github/workflows/scripts/remove-from-coverage.sh" melos exec -c 5 --fail-fast -- "\$MELOS_ROOT_PATH/.github/workflows/scripts/remove-from-coverage.sh"
description: Removes all the ignored files from the coverage report. description: Removes all the ignored files from the coverage report.
select-package: packageFilters:
dir-exists: coverage dirExists: coverage
docs: docs:
run: | run: |
+16
View File
@@ -1,3 +1,19 @@
## Upcoming
🐞 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
- Added `presence` property to `Channel::watch` method.
## 5.3.0 ## 5.3.0
🔄 Changed 🔄 Changed
@@ -6,6 +6,7 @@ version: 1.0.0+1
environment: environment:
sdk: '>=2.17.0 <3.0.0' sdk: '>=2.17.0 <3.0.0'
flutter: ">=1.17.0"
dependencies: dependencies:
cupertino_icons: ^1.0.0 cupertino_icons: ^1.0.0
@@ -463,12 +463,19 @@ class Channel {
client.logger.info('Found ${attachments.length} attachments'); client.logger.info('Found ${attachments.length} attachments');
void updateAttachment(Attachment attachment) { void updateAttachment(Attachment attachment, {bool remove = false}) {
final index = message!.attachments.indexWhere( final index = message!.attachments.indexWhere(
(it) => it.id == attachment.id, (it) => it.id == attachment.id,
); );
if (index != -1) { if (index != -1) {
final newAttachments = [...message!.attachments]..[index] = attachment; // update or remove attachment from message.
final List<Attachment> newAttachments;
if (remove) {
newAttachments = [...message!.attachments]..removeAt(index);
} else {
newAttachments = [...message!.attachments]..[index] = attachment;
}
final updatedMessage = message!.copyWith(attachments: newAttachments); final updatedMessage = message!.copyWith(attachments: newAttachments);
state?.updateMessage(updatedMessage); state?.updateMessage(updatedMessage);
// updating original message for next iteration // updating original message for next iteration
@@ -533,6 +540,14 @@ class Channel {
); );
} }
}).catchError((e, stk) { }).catchError((e, stk) {
if (e is StreamChatNetworkError && e.isRequestCancelledError) {
client.logger.info('Attachment ${it.id} upload cancelled');
// remove attachment from message if cancelled.
updateAttachment(it, remove: true);
return;
}
client.logger.severe('error uploading the attachment', e, stk); client.logger.severe('error uploading the attachment', e, stk);
updateAttachment( updateAttachment(
it.copyWith(uploadState: UploadState.failed(error: e.toString())), it.copyWith(uploadState: UploadState.failed(error: e.toString())),
@@ -1219,11 +1234,11 @@ class Channel {
} }
/// Loads the initial channel state and watches for changes. /// Loads the initial channel state and watches for changes.
Future<ChannelState> watch() async { Future<ChannelState> watch({bool presence = false}) async {
ChannelState response; ChannelState response;
try { try {
response = await query(watch: true); response = await query(watch: true, presence: presence);
} catch (error, stackTrace) { } catch (error, stackTrace) {
if (!_initializedCompleter.isCompleted) { if (!_initializedCompleter.isCompleted) {
_initializedCompleter.completeError(error, stackTrace); _initializedCompleter.completeError(error, stackTrace);
@@ -1613,6 +1628,10 @@ class ChannelClientState {
_listenMemberUnbanned(); _listenMemberUnbanned();
_listenUserStartWatching();
_listenUserStopWatching();
_startCleaningStaleTypingEvents(); _startCleaningStaleTypingEvents();
_startCleaningStalePinnedMessages(); _startCleaningStalePinnedMessages();
@@ -1754,6 +1773,39 @@ class ChannelClientState {
)); ));
} }
void _listenUserStartWatching() {
_subscriptions.add(
_channel.on(EventType.userWatchingStart).listen((event) {
final watcher = event.user;
if (watcher != null) {
final existingWatchers = channelState.watchers;
updateChannelState(channelState.copyWith(
watchers: [
...?existingWatchers,
watcher,
],
));
}
}),
);
}
void _listenUserStopWatching() {
_subscriptions.add(
_channel.on(EventType.userWatchingStop).listen((event) {
final watcher = event.user;
if (watcher != null) {
final existingWatchers = channelState.watchers;
updateChannelState(channelState.copyWith(
watchers: existingWatchers
?.where((user) => user.id != watcher.id)
.toList(growable: false),
));
}
}),
);
}
void _listenMemberUnbanned() { void _listenMemberUnbanned() {
_subscriptions.add(_channel _subscriptions.add(_channel
.on(EventType.userUnbanned) .on(EventType.userUnbanned)
@@ -2083,7 +2135,7 @@ class ChannelClientState {
channelStateStream.map((cs) => cs.watchers), channelStateStream.map((cs) => cs.watchers),
_channel.client.state.usersStream, _channel.client.state.usersStream,
(watchers, users) => watchers!.map((e) => users[e.id] ?? e).toList(), (watchers, users) => watchers!.map((e) => users[e.id] ?? e).toList(),
); ).distinct(const ListEquality().equals);
/// Channel member for the current user. /// Channel member for the current user.
Member? get currentUserMember => members.firstWhereOrNull( Member? get currentUserMember => members.firstWhereOrNull(
@@ -40,7 +40,7 @@ class SortOption<T> {
final int direction; final int direction;
/// Sorting field Comparator required for offline sorting /// Sorting field Comparator required for offline sorting
@JsonKey(ignore: true) @JsonKey(includeToJson: false, includeFromJson: false)
final Comparator<T>? comparator; final Comparator<T>? comparator;
/// Serialize model to json /// Serialize model to json
@@ -74,6 +74,7 @@ class StreamChatNetworkError extends StreamChatError {
ChatErrorCode errorCode, { ChatErrorCode errorCode, {
int? statusCode, int? statusCode,
this.data, this.data,
this.isRequestCancelledError = false,
}) : code = errorCode.code, }) : code = errorCode.code,
statusCode = statusCode ?? data?.statusCode, statusCode = statusCode ?? data?.statusCode,
super(errorCode.message); super(errorCode.message);
@@ -84,6 +85,7 @@ class StreamChatNetworkError extends StreamChatError {
required String message, required String message,
this.statusCode, this.statusCode,
this.data, this.data,
this.isRequestCancelledError = false,
}) : super(message); }) : super(message);
/// ///
@@ -96,10 +98,13 @@ class StreamChatNetworkError extends StreamChatError {
} }
return StreamChatNetworkError.raw( return StreamChatNetworkError.raw(
code: errorResponse?.code ?? -1, code: errorResponse?.code ?? -1,
message: message: errorResponse?.message ??
errorResponse?.message ?? response?.statusMessage ?? error.message, response?.statusMessage ??
error.message ??
'',
statusCode: errorResponse?.statusCode ?? response?.statusCode, statusCode: errorResponse?.statusCode ?? response?.statusCode,
data: errorResponse, data: errorResponse,
isRequestCancelledError: error.type == DioErrorType.cancel,
)..stackTrace = error.stackTrace; )..stackTrace = error.stackTrace;
} }
@@ -112,6 +117,9 @@ class StreamChatNetworkError extends StreamChatError {
/// Response body. please refer to [ErrorResponse]. /// Response body. please refer to [ErrorResponse].
final ErrorResponse? data; final ErrorResponse? data;
/// True, in case the error is due to a cancelled network request.
final bool isRequestCancelledError;
StackTrace? _stackTrace; StackTrace? _stackTrace;
/// ///
@@ -87,8 +87,8 @@ class LoggingInterceptor extends Interceptor {
requestHeaders['contentType'] = options.contentType?.toString(); requestHeaders['contentType'] = options.contentType?.toString();
requestHeaders['responseType'] = options.responseType.toString(); requestHeaders['responseType'] = options.responseType.toString();
requestHeaders['followRedirects'] = options.followRedirects; requestHeaders['followRedirects'] = options.followRedirects;
requestHeaders['connectTimeout'] = options.connectTimeout; requestHeaders['connectTimeout'] = options.connectTimeout?.toString();
requestHeaders['receiveTimeout'] = options.receiveTimeout; requestHeaders['receiveTimeout'] = options.receiveTimeout?.toString();
_printMapAsTable(_logPrintRequest, requestHeaders, header: 'Headers'); _printMapAsTable(_logPrintRequest, requestHeaders, header: 'Headers');
_printMapAsTable(_logPrintRequest, options.extra, header: 'Extras'); _printMapAsTable(_logPrintRequest, options.extra, header: 'Extras');
} }
@@ -101,7 +101,8 @@ class LoggingInterceptor extends Interceptor {
options.data as Map?, options.data as Map?,
header: 'Body', header: 'Body',
); );
} else if (data is FormData) { }
if (data is FormData) {
final formDataMap = <String, dynamic>{} final formDataMap = <String, dynamic>{}
..addEntries(data.fields) ..addEntries(data.fields)
..addEntries(data.files); ..addEntries(data.files);
@@ -121,7 +122,7 @@ class LoggingInterceptor extends Interceptor {
@override @override
void onError(DioError err, ErrorInterceptorHandler handler) { void onError(DioError err, ErrorInterceptorHandler handler) {
if (error) { if (error) {
if (err.type == DioErrorType.response) { if (err.type == DioErrorType.badResponse) {
final uri = err.response?.requestOptions.uri; final uri = err.response?.requestOptions.uri;
_printBoxed( _printBoxed(
_logPrintError, _logPrintError,
@@ -162,7 +163,7 @@ class LoggingInterceptor extends Interceptor {
_logPrintResponse(''); _logPrintResponse('');
_printResponse(_logPrintResponse, response); _printResponse(_logPrintResponse, response);
_logPrintResponse(''); _logPrintResponse('');
_printLine(_logPrintResponse, ''); _logPrintResponse('');
} }
super.onResponse(response, handler); super.onResponse(response, handler);
} }
@@ -29,8 +29,8 @@ class StreamHttpClient {
httpClient = dio ?? Dio() { httpClient = dio ?? Dio() {
httpClient httpClient
..options.baseUrl = _options.baseUrl ..options.baseUrl = _options.baseUrl
..options.receiveTimeout = _options.receiveTimeout.inMilliseconds ..options.receiveTimeout = _options.receiveTimeout
..options.connectTimeout = _options.connectTimeout.inMilliseconds ..options.connectTimeout = _options.connectTimeout
..options.queryParameters = { ..options.queryParameters = {
'api_key': apiKey, 'api_key': apiKey,
..._options.queryParameters, ..._options.queryParameters,
@@ -135,7 +135,6 @@ class Attachment extends Equatable {
late final UploadState uploadState; late final UploadState uploadState;
/// Map of custom channel extraData /// Map of custom channel extraData
@JsonKey(includeIfNull: false)
final Map<String, Object?> extraData; final Map<String, Object?> extraData;
/// The attachment ID. /// The attachment ID.
@@ -146,13 +145,13 @@ class Attachment extends Equatable {
/// Shortcut for file size. /// Shortcut for file size.
/// ///
/// {@macro fileSize} /// {@macro fileSize}
@JsonKey(ignore: true) @JsonKey(includeToJson: false, includeFromJson: false)
int? get fileSize => extraData['file_size'] as int?; int? get fileSize => extraData['file_size'] as int?;
/// Shortcut for file mimeType. /// Shortcut for file mimeType.
/// ///
/// {@macro mimeType} /// {@macro mimeType}
@JsonKey(ignore: true) @JsonKey(includeToJson: false, includeFromJson: false)
String? get mimeType => extraData['mime_type'] as String?; String? get mimeType => extraData['mime_type'] as String?;
/// Known top level fields. /// Known top level fields.
@@ -52,7 +52,7 @@ class AttachmentFile {
/// Byte data for this file. Particularly useful if you want to manipulate /// Byte data for this file. Particularly useful if you want to manipulate
/// its data or easily upload to somewhere else. /// its data or easily upload to somewhere else.
@JsonKey(ignore: true) @JsonKey(includeToJson: false, includeFromJson: false)
final Uint8List? bytes; final Uint8List? bytes;
/// The file size in bytes. /// The file size in bytes.
@@ -1,7 +1,7 @@
// coverage:ignore-file // coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint // 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'; part of 'attachment_file.dart';
@@ -43,10 +43,10 @@ mixin _$UploadState {
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({ TResult? whenOrNull<TResult extends Object?>({
TResult Function()? preparing, TResult? Function()? preparing,
TResult Function(int uploaded, int total)? inProgress, TResult? Function(int uploaded, int total)? inProgress,
TResult Function()? success, TResult? Function()? success,
TResult Function(String error)? failed, TResult? Function(String error)? failed,
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
@@ -68,10 +68,10 @@ mixin _$UploadState {
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({ TResult? mapOrNull<TResult extends Object?>({
TResult Function(Preparing value)? preparing, TResult? Function(Preparing value)? preparing,
TResult Function(InProgress value)? inProgress, TResult? Function(InProgress value)? inProgress,
TResult Function(Success value)? success, TResult? Function(Success value)? success,
TResult Function(Failed value)? failed, TResult? Function(Failed value)? failed,
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
@@ -90,16 +90,18 @@ mixin _$UploadState {
abstract class $UploadStateCopyWith<$Res> { abstract class $UploadStateCopyWith<$Res> {
factory $UploadStateCopyWith( factory $UploadStateCopyWith(
UploadState value, $Res Function(UploadState) then) = UploadState value, $Res Function(UploadState) then) =
_$UploadStateCopyWithImpl<$Res>; _$UploadStateCopyWithImpl<$Res, UploadState>;
} }
/// @nodoc /// @nodoc
class _$UploadStateCopyWithImpl<$Res> implements $UploadStateCopyWith<$Res> { class _$UploadStateCopyWithImpl<$Res, $Val extends UploadState>
implements $UploadStateCopyWith<$Res> {
_$UploadStateCopyWithImpl(this._value, this._then); _$UploadStateCopyWithImpl(this._value, this._then);
final UploadState _value;
// ignore: unused_field // ignore: unused_field
final $Res Function(UploadState) _then; final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
} }
/// @nodoc /// @nodoc
@@ -110,14 +112,12 @@ abstract class _$$PreparingCopyWith<$Res> {
} }
/// @nodoc /// @nodoc
class __$$PreparingCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res> class __$$PreparingCopyWithImpl<$Res>
extends _$UploadStateCopyWithImpl<$Res, _$Preparing>
implements _$$PreparingCopyWith<$Res> { implements _$$PreparingCopyWith<$Res> {
__$$PreparingCopyWithImpl( __$$PreparingCopyWithImpl(
_$Preparing _value, $Res Function(_$Preparing) _then) _$Preparing _value, $Res Function(_$Preparing) _then)
: super(_value, (v) => _then(v as _$Preparing)); : super(_value, _then);
@override
_$Preparing get _value => super._value as _$Preparing;
} }
/// @nodoc /// @nodoc
@@ -162,10 +162,10 @@ class _$Preparing extends Preparing {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({ TResult? whenOrNull<TResult extends Object?>({
TResult Function()? preparing, TResult? Function()? preparing,
TResult Function(int uploaded, int total)? inProgress, TResult? Function(int uploaded, int total)? inProgress,
TResult Function()? success, TResult? Function()? success,
TResult Function(String error)? failed, TResult? Function(String error)? failed,
}) { }) {
return preparing?.call(); return preparing?.call();
} }
@@ -199,10 +199,10 @@ class _$Preparing extends Preparing {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({ TResult? mapOrNull<TResult extends Object?>({
TResult Function(Preparing value)? preparing, TResult? Function(Preparing value)? preparing,
TResult Function(InProgress value)? inProgress, TResult? Function(InProgress value)? inProgress,
TResult Function(Success value)? success, TResult? Function(Success value)? success,
TResult Function(Failed value)? failed, TResult? Function(Failed value)? failed,
}) { }) {
return preparing?.call(this); return preparing?.call(this);
} }
@@ -242,30 +242,30 @@ abstract class _$$InProgressCopyWith<$Res> {
factory _$$InProgressCopyWith( factory _$$InProgressCopyWith(
_$InProgress value, $Res Function(_$InProgress) then) = _$InProgress value, $Res Function(_$InProgress) then) =
__$$InProgressCopyWithImpl<$Res>; __$$InProgressCopyWithImpl<$Res>;
@useResult
$Res call({int uploaded, int total}); $Res call({int uploaded, int total});
} }
/// @nodoc /// @nodoc
class __$$InProgressCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res> class __$$InProgressCopyWithImpl<$Res>
extends _$UploadStateCopyWithImpl<$Res, _$InProgress>
implements _$$InProgressCopyWith<$Res> { implements _$$InProgressCopyWith<$Res> {
__$$InProgressCopyWithImpl( __$$InProgressCopyWithImpl(
_$InProgress _value, $Res Function(_$InProgress) _then) _$InProgress _value, $Res Function(_$InProgress) _then)
: super(_value, (v) => _then(v as _$InProgress)); : super(_value, _then);
@override
_$InProgress get _value => super._value as _$InProgress;
@pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? uploaded = freezed, Object? uploaded = null,
Object? total = freezed, Object? total = null,
}) { }) {
return _then(_$InProgress( return _then(_$InProgress(
uploaded: uploaded == freezed uploaded: null == uploaded
? _value.uploaded ? _value.uploaded
: uploaded // ignore: cast_nullable_to_non_nullable : uploaded // ignore: cast_nullable_to_non_nullable
as int, as int,
total: total == freezed total: null == total
? _value.total ? _value.total
: total // ignore: cast_nullable_to_non_nullable : total // ignore: cast_nullable_to_non_nullable
as int, as int,
@@ -302,19 +302,18 @@ class _$InProgress extends InProgress {
return identical(this, other) || return identical(this, other) ||
(other.runtimeType == runtimeType && (other.runtimeType == runtimeType &&
other is _$InProgress && other is _$InProgress &&
const DeepCollectionEquality().equals(other.uploaded, uploaded) && (identical(other.uploaded, uploaded) ||
const DeepCollectionEquality().equals(other.total, total)); other.uploaded == uploaded) &&
(identical(other.total, total) || other.total == total));
} }
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
int get hashCode => Object.hash( int get hashCode => Object.hash(runtimeType, uploaded, total);
runtimeType,
const DeepCollectionEquality().hash(uploaded),
const DeepCollectionEquality().hash(total));
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@pragma('vm:prefer-inline')
_$$InProgressCopyWith<_$InProgress> get copyWith => _$$InProgressCopyWith<_$InProgress> get copyWith =>
__$$InProgressCopyWithImpl<_$InProgress>(this, _$identity); __$$InProgressCopyWithImpl<_$InProgress>(this, _$identity);
@@ -332,10 +331,10 @@ class _$InProgress extends InProgress {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({ TResult? whenOrNull<TResult extends Object?>({
TResult Function()? preparing, TResult? Function()? preparing,
TResult Function(int uploaded, int total)? inProgress, TResult? Function(int uploaded, int total)? inProgress,
TResult Function()? success, TResult? Function()? success,
TResult Function(String error)? failed, TResult? Function(String error)? failed,
}) { }) {
return inProgress?.call(uploaded, total); return inProgress?.call(uploaded, total);
} }
@@ -369,10 +368,10 @@ class _$InProgress extends InProgress {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({ TResult? mapOrNull<TResult extends Object?>({
TResult Function(Preparing value)? preparing, TResult? Function(Preparing value)? preparing,
TResult Function(InProgress value)? inProgress, TResult? Function(InProgress value)? inProgress,
TResult Function(Success value)? success, TResult? Function(Success value)? success,
TResult Function(Failed value)? failed, TResult? Function(Failed value)? failed,
}) { }) {
return inProgress?.call(this); return inProgress?.call(this);
} }
@@ -422,13 +421,11 @@ abstract class _$$SuccessCopyWith<$Res> {
} }
/// @nodoc /// @nodoc
class __$$SuccessCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res> class __$$SuccessCopyWithImpl<$Res>
extends _$UploadStateCopyWithImpl<$Res, _$Success>
implements _$$SuccessCopyWith<$Res> { implements _$$SuccessCopyWith<$Res> {
__$$SuccessCopyWithImpl(_$Success _value, $Res Function(_$Success) _then) __$$SuccessCopyWithImpl(_$Success _value, $Res Function(_$Success) _then)
: super(_value, (v) => _then(v as _$Success)); : super(_value, _then);
@override
_$Success get _value => super._value as _$Success;
} }
/// @nodoc /// @nodoc
@@ -473,10 +470,10 @@ class _$Success extends Success {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({ TResult? whenOrNull<TResult extends Object?>({
TResult Function()? preparing, TResult? Function()? preparing,
TResult Function(int uploaded, int total)? inProgress, TResult? Function(int uploaded, int total)? inProgress,
TResult Function()? success, TResult? Function()? success,
TResult Function(String error)? failed, TResult? Function(String error)? failed,
}) { }) {
return success?.call(); return success?.call();
} }
@@ -510,10 +507,10 @@ class _$Success extends Success {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({ TResult? mapOrNull<TResult extends Object?>({
TResult Function(Preparing value)? preparing, TResult? Function(Preparing value)? preparing,
TResult Function(InProgress value)? inProgress, TResult? Function(InProgress value)? inProgress,
TResult Function(Success value)? success, TResult? Function(Success value)? success,
TResult Function(Failed value)? failed, TResult? Function(Failed value)? failed,
}) { }) {
return success?.call(this); return success?.call(this);
} }
@@ -552,24 +549,24 @@ abstract class Success extends UploadState {
abstract class _$$FailedCopyWith<$Res> { abstract class _$$FailedCopyWith<$Res> {
factory _$$FailedCopyWith(_$Failed value, $Res Function(_$Failed) then) = factory _$$FailedCopyWith(_$Failed value, $Res Function(_$Failed) then) =
__$$FailedCopyWithImpl<$Res>; __$$FailedCopyWithImpl<$Res>;
@useResult
$Res call({String error}); $Res call({String error});
} }
/// @nodoc /// @nodoc
class __$$FailedCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res> class __$$FailedCopyWithImpl<$Res>
extends _$UploadStateCopyWithImpl<$Res, _$Failed>
implements _$$FailedCopyWith<$Res> { implements _$$FailedCopyWith<$Res> {
__$$FailedCopyWithImpl(_$Failed _value, $Res Function(_$Failed) _then) __$$FailedCopyWithImpl(_$Failed _value, $Res Function(_$Failed) _then)
: super(_value, (v) => _then(v as _$Failed)); : super(_value, _then);
@override
_$Failed get _value => super._value as _$Failed;
@pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? error = freezed, Object? error = null,
}) { }) {
return _then(_$Failed( return _then(_$Failed(
error: error == freezed error: null == error
? _value.error ? _value.error
: error // ignore: cast_nullable_to_non_nullable : error // ignore: cast_nullable_to_non_nullable
as String, as String,
@@ -603,16 +600,16 @@ class _$Failed extends Failed {
return identical(this, other) || return identical(this, other) ||
(other.runtimeType == runtimeType && (other.runtimeType == runtimeType &&
other is _$Failed && other is _$Failed &&
const DeepCollectionEquality().equals(other.error, error)); (identical(other.error, error) || other.error == error));
} }
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
int get hashCode => int get hashCode => Object.hash(runtimeType, error);
Object.hash(runtimeType, const DeepCollectionEquality().hash(error));
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@pragma('vm:prefer-inline')
_$$FailedCopyWith<_$Failed> get copyWith => _$$FailedCopyWith<_$Failed> get copyWith =>
__$$FailedCopyWithImpl<_$Failed>(this, _$identity); __$$FailedCopyWithImpl<_$Failed>(this, _$identity);
@@ -630,10 +627,10 @@ class _$Failed extends Failed {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({ TResult? whenOrNull<TResult extends Object?>({
TResult Function()? preparing, TResult? Function()? preparing,
TResult Function(int uploaded, int total)? inProgress, TResult? Function(int uploaded, int total)? inProgress,
TResult Function()? success, TResult? Function()? success,
TResult Function(String error)? failed, TResult? Function(String error)? failed,
}) { }) {
return failed?.call(error); return failed?.call(error);
} }
@@ -667,10 +664,10 @@ class _$Failed extends Failed {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({ TResult? mapOrNull<TResult extends Object?>({
TResult Function(Preparing value)? preparing, TResult? Function(Preparing value)? preparing,
TResult Function(InProgress value)? inProgress, TResult? Function(InProgress value)? inProgress,
TResult Function(Success value)? success, TResult? Function(Success value)? success,
TResult Function(Failed value)? failed, TResult? Function(Failed value)? failed,
}) { }) {
return failed?.call(this); return failed?.call(this);
} }
@@ -62,19 +62,19 @@ class ChannelModel {
final String type; final String type;
/// The cid of this channel /// The cid of this channel
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final String cid; final String cid;
/// List of user permissions on this channel /// List of user permissions on this channel
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final List<String>? ownCapabilities; final List<String>? ownCapabilities;
/// The channel configuration data /// The channel configuration data
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final ChannelConfig config; final ChannelConfig config;
/// The user that created this channel /// The user that created this channel
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final User? createdBy; final User? createdBy;
/// True if this channel is frozen /// True if this channel is frozen
@@ -82,23 +82,23 @@ class ChannelModel {
final bool frozen; final bool frozen;
/// The date of the last message /// The date of the last message
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final DateTime? lastMessageAt; final DateTime? lastMessageAt;
/// The date of channel creation /// The date of channel creation
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final DateTime createdAt; final DateTime createdAt;
/// The date of the last channel update /// The date of the last channel update
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final DateTime updatedAt; final DateTime updatedAt;
/// The date of channel deletion /// The date of channel deletion
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final DateTime? deletedAt; final DateTime? deletedAt;
/// The count of this channel members /// The count of this channel members
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final int memberCount; final int memberCount;
/// The number of seconds in a cooldown /// The number of seconds in a cooldown
@@ -106,15 +106,15 @@ class ChannelModel {
final int cooldown; final int cooldown;
/// True if the channel is disabled /// True if the channel is disabled
@JsonKey(ignore: true) @JsonKey(includeToJson: false, includeFromJson: false)
bool? get disabled => extraData['disabled'] as bool?; bool? get disabled => extraData['disabled'] as bool?;
/// True if the channel is hidden /// True if the channel is hidden
@JsonKey(ignore: true) @JsonKey(includeToJson: false, includeFromJson: false)
bool? get hidden => extraData['hidden'] as bool?; bool? get hidden => extraData['hidden'] as bool?;
/// The date of the last time channel got truncated /// The date of the last time channel got truncated
@JsonKey(ignore: true) @JsonKey(includeToJson: false, includeFromJson: false)
DateTime? get truncatedAt { DateTime? get truncatedAt {
final truncatedAt = extraData['truncated_at'] as String?; final truncatedAt = extraData['truncated_at'] as String?;
if (truncatedAt == null) return null; if (truncatedAt == null) return null;
@@ -122,11 +122,10 @@ class ChannelModel {
} }
/// Map of custom channel extraData /// Map of custom channel extraData
@JsonKey(includeIfNull: false)
final Map<String, Object?> extraData; final Map<String, Object?> extraData;
/// The team the channel belongs to /// The team the channel belongs to
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final String? team; final String? team;
/// Known top level fields. /// Known top level fields.
@@ -38,30 +38,11 @@ ChannelModel _$ChannelModelFromJson(Map<String, dynamic> json) => ChannelModel(
cooldown: json['cooldown'] as int? ?? 0, cooldown: json['cooldown'] as int? ?? 0,
); );
Map<String, dynamic> _$ChannelModelToJson(ChannelModel instance) { Map<String, dynamic> _$ChannelModelToJson(ChannelModel instance) =>
final val = <String, dynamic>{ <String, dynamic>{
'id': instance.id, 'id': instance.id,
'type': instance.type, 'type': instance.type,
}; 'frozen': instance.frozen,
'cooldown': instance.cooldown,
void writeNotNull(String key, dynamic value) { 'extra_data': instance.extraData,
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;
}
@@ -95,14 +95,11 @@ class Message extends Equatable {
final String? text; final String? text;
/// The status of a sending message. /// The status of a sending message.
@JsonKey(ignore: true) @JsonKey(includeFromJson: false, includeToJson: false)
final MessageSendingStatus status; final MessageSendingStatus status;
/// The message type. /// The message type.
@JsonKey( @JsonKey(includeToJson: false)
includeIfNull: false,
toJson: Serializer.readOnly,
)
final String type; final String type;
/// The list of attachments, either provided by the user or generated from a /// 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; final List<User> mentionedUsers;
/// A map describing the count of number of every reaction. /// A map describing the count of number of every reaction.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final Map<String, int>? reactionCounts; final Map<String, int>? reactionCounts;
/// A map describing the count of score of every reaction. /// A map describing the count of score of every reaction.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final Map<String, int>? reactionScores; final Map<String, int>? reactionScores;
/// The latest reactions to the message created by any user. /// The latest reactions to the message created by any user.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final List<Reaction>? latestReactions; final List<Reaction>? latestReactions;
/// The reactions added to the message by the current user. /// The reactions added to the message by the current user.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final List<Reaction>? ownReactions; final List<Reaction>? ownReactions;
/// The ID of the parent message, if the message is a thread reply. /// The ID of the parent message, if the message is a thread reply.
final String? parentId; final String? parentId;
/// A quoted reply message. /// A quoted reply message.
@JsonKey(toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final Message? quotedMessage; final Message? quotedMessage;
final String? _quotedMessageId; final String? _quotedMessageId;
@@ -143,11 +140,11 @@ class Message extends Equatable {
String? get quotedMessageId => _quotedMessageId ?? quotedMessage?.id; String? get quotedMessageId => _quotedMessageId ?? quotedMessage?.id;
/// Reserved field indicating the number of replies for this message. /// Reserved field indicating the number of replies for this message.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final int? replyCount; final int? replyCount;
/// Reserved field indicating the thread participants for this message. /// Reserved field indicating the thread participants for this message.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final List<User>? threadParticipants; final List<User>? threadParticipants;
/// Check if this message needs to show in the channel. /// Check if this message needs to show in the channel.
@@ -157,41 +154,38 @@ class Message extends Equatable {
final bool silent; final bool silent;
/// If true the message is shadowed. /// If true the message is shadowed.
@JsonKey( @JsonKey(includeToJson: false)
includeIfNull: false,
toJson: Serializer.readOnly,
)
final bool shadowed; final bool shadowed;
/// A used command name. /// A used command name.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final String? command; final String? command;
final DateTime? _createdAt; final DateTime? _createdAt;
/// Reserved field indicating when the message was deleted. /// Reserved field indicating when the message was deleted.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final DateTime? deletedAt; final DateTime? deletedAt;
/// Reserved field indicating when the message was created. /// Reserved field indicating when the message was created.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
DateTime get createdAt => _createdAt ?? DateTime.now(); DateTime get createdAt => _createdAt ?? DateTime.now();
final DateTime? _updatedAt; final DateTime? _updatedAt;
/// Reserved field indicating when the message was updated last time. /// 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(); DateTime get updatedAt => _updatedAt ?? DateTime.now();
/// User who sent the message. /// User who sent the message.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final User? user; final User? user;
/// If true the message is pinned. /// If true the message is pinned.
final bool pinned; final bool pinned;
/// Reserved field indicating when the message was pinned. /// Reserved field indicating when the message was pinned.
@JsonKey(toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final DateTime? pinnedAt; final DateTime? pinnedAt;
/// Reserved field indicating when the message will expire. /// Reserved field indicating when the message will expire.
@@ -200,11 +194,10 @@ class Message extends Equatable {
final DateTime? pinExpires; final DateTime? pinExpires;
/// Reserved field indicating who pinned the message. /// Reserved field indicating who pinned the message.
@JsonKey(toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final User? pinnedBy; final User? pinnedBy;
/// Message custom extraData. /// Message custom extraData.
@JsonKey(includeIfNull: false)
final Map<String, Object?> extraData; final Map<String, Object?> extraData;
/// True if the message is a system info. /// True if the message is a system info.
@@ -217,7 +210,7 @@ class Message extends Equatable {
bool get isEphemeral => type == 'ephemeral'; bool get isEphemeral => type == 'ephemeral';
/// A Map of translations. /// A Map of translations.
@JsonKey(includeIfNull: false) @JsonKey(includeToJson: false)
final Map<String, String>? i18n; final Map<String, String>? i18n;
/// Known top level fields. /// Known top level fields.
@@ -71,43 +71,16 @@ Message _$MessageFromJson(Map<String, dynamic> json) => Message(
), ),
); );
Map<String, dynamic> _$MessageToJson(Message instance) { Map<String, dynamic> _$MessageToJson(Message instance) => <String, dynamic>{
final val = <String, dynamic>{ 'id': instance.id,
'id': instance.id, 'text': instance.text,
'text': instance.text, 'attachments': instance.attachments.map((e) => e.toJson()).toList(),
}; 'mentioned_users': User.toIds(instance.mentionedUsers),
'parent_id': instance.parentId,
void writeNotNull(String key, dynamic value) { 'quoted_message_id': instance.quotedMessageId,
if (value != null) { 'show_in_channel': instance.showInChannel,
val[key] = value; 'silent': instance.silent,
} 'pinned': instance.pinned,
} 'pin_expires': instance.pinExpires?.toIso8601String(),
'extra_data': instance.extraData,
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;
}
@@ -33,22 +33,21 @@ class Reaction {
final String type; final String type;
/// The date of the reaction /// The date of the reaction
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final DateTime createdAt; final DateTime createdAt;
/// The user that sent the reaction /// The user that sent the reaction
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final User? user; final User? user;
/// The score of the reaction (ie. number of reactions sent) /// The score of the reaction (ie. number of reactions sent)
final int score; final int score;
/// The userId that sent the reaction /// The userId that sent the reaction
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final String? userId; final String? userId;
/// Reaction custom extraData /// Reaction custom extraData
@JsonKey(includeIfNull: false)
final Map<String, Object?> extraData; final Map<String, Object?> extraData;
/// Map of custom user 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 {}, extraData: json['extra_data'] as Map<String, dynamic>? ?? const {},
); );
Map<String, dynamic> _$ReactionToJson(Reaction instance) { Map<String, dynamic> _$ReactionToJson(Reaction instance) => <String, dynamic>{
final val = <String, dynamic>{ 'message_id': instance.messageId,
'message_id': instance.messageId, 'type': instance.type,
'type': instance.type, 'score': instance.score,
}; 'extra_data': instance.extraData,
};
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;
}
@@ -79,7 +79,7 @@ class User extends Equatable {
/// Shortcut for user name. /// Shortcut for user name.
/// ///
/// {@macro name} /// {@macro name}
@JsonKey(ignore: true) @JsonKey(includeToJson: false, includeFromJson: false)
String get name { String get name {
if (extraData.containsKey('name') && extraData['name'] != null) { if (extraData.containsKey('name') && extraData['name'] != null) {
final name = extraData['name']! as String; final name = extraData['name']! as String;
@@ -91,48 +91,39 @@ class User extends Equatable {
/// Shortcut for user image. /// Shortcut for user image.
/// ///
/// {@macro image} /// {@macro image}
@JsonKey(ignore: true) @JsonKey(includeToJson: false, includeFromJson: false)
String? get image => extraData['image'] as String?; String? get image => extraData['image'] as String?;
/// User role. /// User role.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final String? role; final String? role;
/// User teams /// User teams
@JsonKey( @JsonKey(includeToJson: false)
includeIfNull: false,
toJson: Serializer.readOnly,
)
final List<String> teams; final List<String> teams;
/// Date of user creation. /// Date of user creation.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final DateTime createdAt; final DateTime createdAt;
/// Date of last user update. /// Date of last user update.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final DateTime updatedAt; final DateTime updatedAt;
/// Date of last user connection. /// Date of last user connection.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final DateTime? lastActive; final DateTime? lastActive;
/// True if user is online. /// True if user is online.
@JsonKey( @JsonKey(includeToJson: false)
includeIfNull: false,
toJson: Serializer.readOnly,
)
final bool online; final bool online;
/// True if user is banned from the chat. /// True if user is banned from the chat.
@JsonKey( @JsonKey(includeToJson: false)
includeIfNull: false,
toJson: Serializer.readOnly,
)
final bool banned; final bool banned;
/// The date at which the ban will expire. /// The date at which the ban will expire.
@JsonKey(includeIfNull: false, toJson: Serializer.readOnly) @JsonKey(includeToJson: false)
final DateTime? banExpires; final DateTime? banExpires;
/// The language this user prefers. /// The language this user prefers.
@@ -140,7 +131,6 @@ class User extends Equatable {
final String? language; final String? language;
/// Map of custom user extraData. /// Map of custom user extraData.
@JsonKey(includeIfNull: false)
final Map<String, Object?> extraData; final Map<String, Object?> extraData;
/// List of users to list of userIds. /// 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); writeNotNull('language', instance.language);
val['extra_data'] = instance.extraData; val['extra_data'] = instance.extraData;
return val; 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 /// Helper class for serialization to and from json
class Serializer { 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 /// Takes unknown json keys and puts them in the `extra_data` key
static Map<String, dynamic> moveToExtraDataFromRoot( static Map<String, dynamic> moveToExtraDataFromRoot(
Map<String, dynamic> json, Map<String, dynamic> json,
@@ -36,6 +36,12 @@ class EventType {
/// Event sent when updating a message /// Event sent when updating a message
static const String messageUpdated = 'message.updated'; static const String messageUpdated = 'message.updated';
/// Event sent when a user starts watching a channel
static const String userWatchingStart = 'user.watching.start';
/// Event sent when a user stops watching a channel
static const String userWatchingStop = 'user.watching.stop';
/// Event sent when reading a message /// Event sent when reading a message
static const String messageRead = 'message.read'; static const String messageRead = 'message.read';
+19 -19
View File
@@ -9,26 +9,26 @@ environment:
sdk: '>=2.17.0 <3.0.0' sdk: '>=2.17.0 <3.0.0'
dependencies: dependencies:
async: ^2.5.0 async: ^2.10.0
collection: ^1.15.0 collection: ^1.17.0
dio: ^4.0.0 dio: ^5.1.1
equatable: ^2.0.0 equatable: ^2.0.5
freezed_annotation: ^2.0.3 freezed_annotation: ^2.2.0
http_parser: ^4.0.0 http_parser: ^4.0.2
jose: ^0.3.2 jose: ^0.3.3
json_annotation: ^4.5.0 json_annotation: ^4.8.0
logging: ^1.0.1 logging: ^1.1.1
meta: ^1.3.0 meta: ^1.8.0
mime: ^1.0.0 mime: ^1.0.4
rate_limiter: ^1.0.0 rate_limiter: ^1.0.0
rxdart: ^0.27.0 rxdart: ^0.27.7
uuid: ^3.0.4 uuid: ^3.0.7
web_socket_channel: ^2.0.0 web_socket_channel: ^2.3.0
dev_dependencies: dev_dependencies:
build_runner: ^2.0.1 build_runner: ^2.3.3
dart_code_metrics: ^4.4.0 dart_code_metrics: ^5.7.0
freezed: ^2.0.3 freezed: ^2.3.2
json_serializable: ^6.2.0 json_serializable: ^6.6.1
mocktail: ^0.3.0 mocktail: ^0.3.0
test: ^1.17.12 test: ^1.24.1
+25 -101
View File
@@ -1,4 +1,3 @@
{ {
"channel": { "channel": {
"id": "dev", "id": "dev",
@@ -18,400 +17,325 @@
"text": "fasdfa", "text": "fasdfa",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "dry-meadow-0-e8e74482-b4cd-48db-9d1e-30e6c191786f", "id": "dry-meadow-0-e8e74482-b4cd-48db-9d1e-30e6c191786f",
"text": "test message", "text": "test message",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "dry-meadow-0-53e6299f-9b97-4a9c-a27e-7e2dde49b7e0", "id": "dry-meadow-0-53e6299f-9b97-4a9c-a27e-7e2dde49b7e0",
"text": "test message", "text": "test message",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "dry-meadow-0-80925be0-786e-40a5-b225-486518dafd35", "id": "dry-meadow-0-80925be0-786e-40a5-b225-486518dafd35",
"text": "asdfadf", "text": "asdfadf",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "dry-meadow-0-64d7970f-ede8-4b31-9738-1bc1756d2bfe", "id": "dry-meadow-0-64d7970f-ede8-4b31-9738-1bc1756d2bfe",
"text": "test", "text": "test",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "withered-cell-0-84cbd760-cf55-4f7e-9207-c5f66cccc6dc", "id": "withered-cell-0-84cbd760-cf55-4f7e-9207-c5f66cccc6dc",
"text": "hi", "text": "hi",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "dry-meadow-0-e9203588-43c3-40b1-91f7-f217fc42aa53", "id": "dry-meadow-0-e9203588-43c3-40b1-91f7-f217fc42aa53",
"text": "fantastic", "text": "fantastic",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "withered-cell-0-7e3552d7-7a0d-45f2-a856-e91b23a7e240", "id": "withered-cell-0-7e3552d7-7a0d-45f2-a856-e91b23a7e240",
"text": "nice to meet you", "text": "nice to meet you",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "dry-meadow-0-1ffeafd4-e4fc-4c84-9394-9d7cb10fff42", "id": "dry-meadow-0-1ffeafd4-e4fc-4c84-9394-9d7cb10fff42",
"text": "hey", "text": "hey",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "dry-meadow-0-3f147324-12c8-4b41-9fb5-2db88d065efa", "id": "dry-meadow-0-3f147324-12c8-4b41-9fb5-2db88d065efa",
"text": "hello, everyone", "text": "hello, everyone",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "dry-meadow-0-51a348ae-0c0a-44de-a556-eac7891c0cf0", "id": "dry-meadow-0-51a348ae-0c0a-44de-a556-eac7891c0cf0",
"text": "who is there?", "text": "who is there?",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "icy-recipe-7-a29e237b-8d81-4a97-9bc8-d42bca3f1356", "id": "icy-recipe-7-a29e237b-8d81-4a97-9bc8-d42bca3f1356",
"text": "하이", "text": "하이",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "icy-recipe-7-935c396e-ddf8-4a9a-951c-0a12fa5bf055", "id": "icy-recipe-7-935c396e-ddf8-4a9a-951c-0a12fa5bf055",
"text": "what are you doing?", "text": "what are you doing?",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "throbbing-boat-5-1e4d5730-5ff0-4d25-9948-9f34ffda43e4", "id": "throbbing-boat-5-1e4d5730-5ff0-4d25-9948-9f34ffda43e4",
"text": "👍", "text": "👍",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "snowy-credit-3-3e0c1a0d-d22f-42ee-b2a1-f9f49477bf21", "id": "snowy-credit-3-3e0c1a0d-d22f-42ee-b2a1-f9f49477bf21",
"text": "sdasas", "text": "sdasas",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "snowy-credit-3-3319537e-2d0e-4876-8170-a54f046e4b7d", "id": "snowy-credit-3-3319537e-2d0e-4876-8170-a54f046e4b7d",
"text": "cjshsa", "text": "cjshsa",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "snowy-credit-3-cfaf0b46-1daa-49c5-947c-b16d6697487d", "id": "snowy-credit-3-cfaf0b46-1daa-49c5-947c-b16d6697487d",
"text": "nhisagdhsadz", "text": "nhisagdhsadz",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "snowy-credit-3-cebe25a7-a3a3-49fc-9919-91c6725e81f3", "id": "snowy-credit-3-cebe25a7-a3a3-49fc-9919-91c6725e81f3",
"text": "hvadhsahzd", "text": "hvadhsahzd",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "divine-glade-9-0cea9262-5766-48e9-8b22-311870aed3bf", "id": "divine-glade-9-0cea9262-5766-48e9-8b22-311870aed3bf",
"text": "hello", "text": "hello",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "red-firefly-9-c4e9007b-bb7d-4238-ae08-5f8e3cd03d73", "id": "red-firefly-9-c4e9007b-bb7d-4238-ae08-5f8e3cd03d73",
"text": "hello", "text": "hello",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "bitter-glade-2-02aee4eb-4093-4736-808b-2de75820e854", "id": "bitter-glade-2-02aee4eb-4093-4736-808b-2de75820e854",
"text": "hello", "text": "hello",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "morning-sea-1-0c700bcb-46dd-4224-b590-e77bdbccc480", "id": "morning-sea-1-0c700bcb-46dd-4224-b590-e77bdbccc480",
"text": "http://jaeger.ui.gtstrm.com/", "text": "http://jaeger.ui.gtstrm.com/",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "ancient-salad-0-53e8b4e6-5b7b-43ad-aeee-8bfb6a9ed0be", "id": "ancient-salad-0-53e8b4e6-5b7b-43ad-aeee-8bfb6a9ed0be",
"text": "hi", "text": "hi",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "ancient-salad-0-8c225075-bd4c-42e2-8024-530aae13cd40", "id": "ancient-salad-0-8c225075-bd4c-42e2-8024-530aae13cd40",
"text": "hi", "text": "hi",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
}, },
{ {
"id": "proud-sea-7-17802096-cbf8-4e3c-addd-4ee31f4c8b5c", "id": "proud-sea-7-17802096-cbf8-4e3c-addd-4ee31f4c8b5c",
"text": "😃", "text": "😃",
"attachments": [], "attachments": [],
"parent_id": null, "parent_id": null,
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"show_in_channel": null, "show_in_channel": null,
"mentioned_users": [], "mentioned_users": [],
"status": "SENT", "status": "SENT",
"silent": false, "silent": false,
"pinned": false, "pinned": false,
"pinned_at": null, "pin_expires": null
"pin_expires": null,
"pinned_by": null
} }
], ],
"pinned_messages": [], "pinned_messages": [],
@@ -18,12 +18,9 @@
], ],
"mentioned_users": [], "mentioned_users": [],
"parent_id": "parentId", "parent_id": "parentId",
"quoted_message": null,
"quoted_message_id": null, "quoted_message_id": null,
"pinned": false, "pinned": false,
"pinned_at": null,
"pin_expires": null, "pin_expires": null,
"pinned_by": null,
"show_in_channel": true, "show_in_channel": true,
"hey": "test" "hey": "test"
} }
@@ -394,7 +394,12 @@ void main() {
path, path,
data: {'language': language}, data: {'language': language},
)).thenAnswer((_) async => successResponse(path, data: { )).thenAnswer((_) async => successResponse(path, data: {
'message': translatedMessage.toJson(), 'message': {
...translatedMessage.toJson(),
'i18n': {
language: translatedMessageText,
},
},
})); }));
final res = await messageApi.translateMessage(messageId, language); final res = await messageApi.translateMessage(messageId, language);
@@ -129,7 +129,11 @@ void main() {
await client.get('path'); await client.get('path');
} on StreamChatNetworkError catch (e) { } on StreamChatNetworkError catch (e) {
expect(e, isA<StreamChatNetworkError>()); 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.',
);
} }
}); });
+16
View File
@@ -1,3 +1,19 @@
## Upcoming
🐞 Fixed
- [#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
- Now it is possible to customize the max lines of the title of a url attachment. Before it was always 1 line.
- Added `attachmentActionsModalBuilder` parameter to `StreamMessageWidget` that allows to customize `AttachmentActionsModal`.
🔄 Changed
- Updated dependencies to resolvable versions.
## 5.3.0 ## 5.3.0
🔄 Changed 🔄 Changed
@@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 51; objectVersion = 54;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@@ -199,6 +199,7 @@
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
@@ -235,6 +236,7 @@
}; };
9740EEB61CF901F6004384FC /* Run Script */ = { 9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
@@ -61,5 +61,7 @@
<string>Explain why your app uses the mic</string> <string>Explain why your app uses the mic</string>
<key>CADisableMinimumFrameDurationOnPhone</key> <key>CADisableMinimumFrameDurationOnPhone</key>
<true/> <true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict> </dict>
</plist> </plist>
@@ -177,7 +177,7 @@ class _SplitViewState extends State<SplitView> {
: Center( : Center(
child: Text( child: Text(
'Pick a channel to show the messages 💬', '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( : Center(
child: Text( child: Text(
'Pick a channel to show the messages 💬', 'Pick a channel to show the messages 💬',
style: Theme.of(context).textTheme.headline5, style: Theme.of(context).textTheme.headlineSmall,
), ),
), ),
), ),
@@ -74,6 +74,9 @@ class MyApp extends StatelessWidget {
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
), ),
ownMessageTheme: const StreamMessageThemeData(
urlAttachmentTitleMaxLine: 1,
),
otherMessageTheme: StreamMessageThemeData( otherMessageTheme: StreamMessageThemeData(
messageBackgroundColor: colorTheme.textHighEmphasis, messageBackgroundColor: colorTheme.textHighEmphasis,
messageTextStyle: TextStyle( messageTextStyle: TextStyle(
@@ -82,6 +85,7 @@ class MyApp extends StatelessWidget {
avatarTheme: StreamAvatarThemeData( avatarTheme: StreamAvatarThemeData(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
urlAttachmentTitleMaxLine: 1,
), ),
).merge(defaultTheme); ).merge(defaultTheme);
@@ -8,10 +8,9 @@
#include <dart_vlc/dart_vlc_plugin.h> #include <dart_vlc/dart_vlc_plugin.h>
#include <desktop_drop/desktop_drop_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 <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h> #include <url_launcher_linux/url_launcher_plugin.h>
#include <window_manager/window_manager_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) dart_vlc_registrar = g_autoptr(FlPluginRegistrar) dart_vlc_registrar =
@@ -20,16 +19,13 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) desktop_drop_registrar = g_autoptr(FlPluginRegistrar) desktop_drop_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopDropPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopDropPlugin");
desktop_drop_plugin_register_with_registrar(desktop_drop_registrar); desktop_drop_plugin_register_with_registrar(desktop_drop_registrar);
g_autoptr(FlPluginRegistrar) screen_retriever_registrar = g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
screen_retriever_plugin_register_with_registrar(screen_retriever_registrar); file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar = g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin");
sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar); sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); 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 list(APPEND FLUTTER_PLUGIN_LIST
dart_vlc dart_vlc
desktop_drop desktop_drop
screen_retriever file_selector_linux
sqlite3_flutter_libs sqlite3_flutter_libs
url_launcher_linux url_launcher_linux
window_manager
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
@@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 51; objectVersion = 54;
objects = { objects = {
/* Begin PBXAggregateTarget section */ /* Begin PBXAggregateTarget section */
@@ -203,7 +203,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 0920; LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 0930; LastUpgradeCheck = 1300;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
33CC10EC2044A3C60003C045 = { 33CC10EC2044A3C60003C045 = {
@@ -256,6 +256,7 @@
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
3399D490228B24CF009A79C7 /* ShellScript */ = { 3399D490228B24CF009A79C7 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
@@ -404,7 +405,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11; MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx; SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;
@@ -484,7 +485,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11; MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx; SDKROOT = macosx;
@@ -531,7 +532,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11; MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx; SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1000" LastUpgradeVersion = "1300"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@@ -19,6 +19,7 @@ version: 1.0.0+1
environment: environment:
sdk: '>=2.17.0 <3.0.0' sdk: '>=2.17.0 <3.0.0'
flutter: ">=1.17.0"
dependencies: dependencies:
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
@@ -27,7 +28,7 @@ dependencies:
cupertino_icons: ^1.0.4 cupertino_icons: ^1.0.4
flutter: flutter:
sdk: flutter sdk: flutter
responsive_builder: ^0.4.2 responsive_builder: ^0.6.4
stream_chat_flutter: stream_chat_flutter:
path: ../ path: ../
stream_chat_localizations: stream_chat_localizations:
@@ -6,16 +6,14 @@
#include "generated_plugin_registrant.h" #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 <dart_vlc/dart_vlc_plugin.h>
#include <desktop_drop/desktop_drop_plugin.h> #include <desktop_drop/desktop_drop_plugin.h>
#include <file_selector_windows/file_selector_windows.h> #include <file_selector_windows/file_selector_windows.h>
#include <flutter_native_view/flutter_native_view_plugin.h> #include <share_plus/share_plus_windows_plugin_c_api.h>
#include <screen_retriever/screen_retriever_plugin.h>
#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h> #include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
#include <thumblr_windows/thumblr_windows_plugin.h> #include <thumblr_windows/thumblr_windows_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h> #include <url_launcher_windows/url_launcher_windows.h>
#include <window_manager/window_manager_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
ConnectivityPlusWindowsPluginRegisterWithRegistrar( ConnectivityPlusWindowsPluginRegisterWithRegistrar(
@@ -26,16 +24,12 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("DesktopDropPlugin")); registry->GetRegistrarForPlugin("DesktopDropPlugin"));
FileSelectorWindowsRegisterWithRegistrar( FileSelectorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSelectorWindows")); registry->GetRegistrarForPlugin("FileSelectorWindows"));
FlutterNativeViewPluginRegisterWithRegistrar( SharePlusWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterNativeViewPlugin")); registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
ScreenRetrieverPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
Sqlite3FlutterLibsPluginRegisterWithRegistrar( Sqlite3FlutterLibsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin"));
ThumblrWindowsPluginRegisterWithRegistrar( ThumblrWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ThumblrWindowsPlugin")); registry->GetRegistrarForPlugin("ThumblrWindowsPlugin"));
UrlLauncherWindowsRegisterWithRegistrar( UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows")); registry->GetRegistrarForPlugin("UrlLauncherWindows"));
WindowManagerPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("WindowManagerPlugin"));
} }
@@ -3,16 +3,14 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
connectivity_plus_windows connectivity_plus
dart_vlc dart_vlc
desktop_drop desktop_drop
file_selector_windows file_selector_windows
flutter_native_view share_plus
screen_retriever
sqlite3_flutter_libs sqlite3_flutter_libs
thumblr_windows thumblr_windows
url_launcher_windows url_launcher_windows
window_manager
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
@@ -17,6 +17,7 @@ class StreamGiphyAttachment extends StreamAttachmentWidget {
this.onShowMessage, this.onShowMessage,
this.onReplyMessage, this.onReplyMessage,
this.onAttachmentTap, this.onAttachmentTap,
this.attachmentActionsModalBuilder,
}); });
/// {@macro showMessageCallback} /// {@macro showMessageCallback}
@@ -28,6 +29,9 @@ class StreamGiphyAttachment extends StreamAttachmentWidget {
/// {@macro onAttachmentTap} /// {@macro onAttachmentTap}
final OnAttachmentTap? onAttachmentTap; final OnAttachmentTap? onAttachmentTap;
/// {@macro attachmentActionsBuilder}
final AttachmentActionsBuilder? attachmentActionsModalBuilder;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final imageUrl = final imageUrl =
@@ -260,6 +264,7 @@ class StreamGiphyAttachment extends StreamAttachmentWidget {
userName: message.user!.name, userName: message.user!.name,
onShowMessage: onShowMessage, onShowMessage: onShowMessage,
onReplyMessage: onReplyMessage, onReplyMessage: onReplyMessage,
attachmentActionsModalBuilder: attachmentActionsModalBuilder,
), ),
); );
}, },
@@ -22,6 +22,7 @@ class StreamImageAttachment extends StreamAttachmentWidget {
this.imageThumbnailSize = const Size(400, 400), this.imageThumbnailSize = const Size(400, 400),
this.imageThumbnailResizeType = 'clip', this.imageThumbnailResizeType = 'clip',
this.imageThumbnailCropType = 'center', this.imageThumbnailCropType = 'center',
this.attachmentActionsModalBuilder,
}); });
/// The [StreamMessageThemeData] to use for the image title /// The [StreamMessageThemeData] to use for the image title
@@ -52,6 +53,9 @@ class StreamImageAttachment extends StreamAttachmentWidget {
/// Defaults to [center] /// Defaults to [center]
final String /*center|top|bottom|left|right*/ imageThumbnailCropType; final String /*center|top|bottom|left|right*/ imageThumbnailCropType;
/// {@macro attachmentActionsBuilder}
final AttachmentActionsBuilder? attachmentActionsModalBuilder;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return source.when( return source.when(
@@ -161,6 +165,8 @@ class StreamImageAttachment extends StreamAttachmentWidget {
userName: message.user!.name, userName: message.user!.name,
onShowMessage: onShowMessage, onShowMessage: onShowMessage,
onReplyMessage: onReplyMessage, onReplyMessage: onReplyMessage,
attachmentActionsModalBuilder:
attachmentActionsModalBuilder,
), ),
); );
}, },
@@ -18,6 +18,7 @@ class StreamImageGroup extends StatelessWidget {
this.imageThumbnailSize = const Size(400, 400), this.imageThumbnailSize = const Size(400, 400),
this.imageThumbnailResizeType = 'clip', this.imageThumbnailResizeType = 'clip',
this.imageThumbnailCropType = 'center', this.imageThumbnailCropType = 'center',
this.attachmentActionsModalBuilder,
}); });
/// List of attachments to show /// List of attachments to show
@@ -54,6 +55,9 @@ class StreamImageGroup extends StatelessWidget {
/// Defaults to [center] /// Defaults to [center]
final String /*center|top|bottom|left|right*/ imageThumbnailCropType; final String /*center|top|bottom|left|right*/ imageThumbnailCropType;
/// {@macro attachmentActionsBuilder}
final AttachmentActionsBuilder? attachmentActionsModalBuilder;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ConstrainedBox( return ConstrainedBox(
@@ -154,6 +158,7 @@ class StreamImageGroup extends StatelessWidget {
userName: message.user!.name, userName: message.user!.name,
onShowMessage: onShowMessage, onShowMessage: onShowMessage,
onReplyMessage: onReplyMessage, onReplyMessage: onReplyMessage,
attachmentActionsModalBuilder: attachmentActionsModalBuilder,
), ),
), ),
), ),
@@ -170,6 +175,7 @@ class StreamImageGroup extends StatelessWidget {
imageThumbnailSize: imageThumbnailSize, imageThumbnailSize: imageThumbnailSize,
imageThumbnailResizeType: imageThumbnailResizeType, imageThumbnailResizeType: imageThumbnailResizeType,
imageThumbnailCropType: imageThumbnailCropType, imageThumbnailCropType: imageThumbnailCropType,
attachmentActionsModalBuilder: attachmentActionsModalBuilder,
); );
} }
} }
@@ -107,7 +107,7 @@ class StreamUrlAttachment extends StatelessWidget {
if (urlAttachment.title != null) if (urlAttachment.title != null)
Text( Text(
urlAttachment.title!.trim(), urlAttachment.title!.trim(),
maxLines: 1, maxLines: messageTheme.urlAttachmentTitleMaxLine ?? 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: chatThemeData.textTheme.body style: chatThemeData.textTheme.body
.copyWith(fontWeight: FontWeight.w700), .copyWith(fontWeight: FontWeight.w700),
@@ -17,6 +17,7 @@ class StreamVideoAttachment extends StreamAttachmentWidget {
this.onShowMessage, this.onShowMessage,
this.onReplyMessage, this.onReplyMessage,
this.onAttachmentTap, this.onAttachmentTap,
this.attachmentActionsModalBuilder,
}); });
/// The [StreamMessageThemeData] to use for the title /// The [StreamMessageThemeData] to use for the title
@@ -31,6 +32,9 @@ class StreamVideoAttachment extends StreamAttachmentWidget {
/// {@macro onAttachmentTap} /// {@macro onAttachmentTap}
final OnAttachmentTap? onAttachmentTap; final OnAttachmentTap? onAttachmentTap;
/// {@macro attachmentActionsBuilder}
final AttachmentActionsBuilder? attachmentActionsModalBuilder;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return source.when( return source.when(
@@ -86,6 +90,8 @@ class StreamVideoAttachment extends StreamAttachmentWidget {
userName: message.user!.name, userName: message.user!.name,
onShowMessage: onShowMessage, onShowMessage: onShowMessage,
onReplyMessage: onReplyMessage, onReplyMessage: onReplyMessage,
attachmentActionsModalBuilder:
attachmentActionsModalBuilder,
), ),
), ),
), ),
@@ -162,8 +162,8 @@ class StreamChannelHeader extends StatelessWidget
showMessage: showConnectionStateTile && showStatus, showMessage: showConnectionStateTile && showStatus,
message: statusString, message: statusString,
child: AppBar( child: AppBar(
toolbarTextStyle: theme.textTheme.bodyText2, toolbarTextStyle: theme.textTheme.bodyMedium,
titleTextStyle: theme.textTheme.headline6, titleTextStyle: theme.textTheme.titleLarge,
systemOverlayStyle: theme.brightness == Brightness.dark systemOverlayStyle: theme.brightness == Brightness.dark
? SystemUiOverlayStyle.light ? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark, : SystemUiOverlayStyle.dark,
@@ -131,8 +131,8 @@ class StreamChannelListHeader extends StatelessWidget
showMessage: showConnectionStateTile && showStatus, showMessage: showConnectionStateTile && showStatus,
message: statusString, message: statusString,
child: AppBar( child: AppBar(
toolbarTextStyle: theme.textTheme.bodyText2, toolbarTextStyle: theme.textTheme.bodyMedium,
titleTextStyle: theme.textTheme.headline6, titleTextStyle: theme.textTheme.titleLarge,
systemOverlayStyle: theme.brightness == Brightness.dark systemOverlayStyle: theme.brightness == Brightness.dark
? SystemUiOverlayStyle.light ? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark, : SystemUiOverlayStyle.dark,
@@ -181,7 +181,10 @@ class StreamChannelListHeader extends StatelessWidget
package: 'stream_chat_flutter', package: 'stream_chat_flutter',
width: 24, width: 24,
height: 24, height: 24,
color: color, colorFilter: ColorFilter.mode(
color,
BlendMode.srcIn,
),
); );
}, },
), ),
@@ -1,7 +1,6 @@
import 'dart:io'; import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:file_selector/file_selector.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
@@ -61,6 +60,7 @@ class StreamGalleryFooter extends StatefulWidget
class _StreamGalleryFooterState extends State<StreamGalleryFooter> { class _StreamGalleryFooterState extends State<StreamGalleryFooter> {
final shareButtonKey = GlobalKey(); final shareButtonKey = GlobalKey();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
const showShareButton = !kIsWeb; const showShareButton = !kIsWeb;
@@ -108,12 +108,19 @@ class _StreamGalleryFooterState extends State<StreamGalleryFooter> {
await file.writeAsBytes(bytes); await file.writeAsBytes(bytes);
final box = final box =
shareButtonKey.currentContext?.findRenderObject(); shareButtonKey.currentContext?.findRenderObject();
final size = shareButtonKey.currentContext?.size;
final position = final position =
(box! as RenderBox).localToGlobal(Offset.zero); (box! as RenderBox).localToGlobal(Offset.zero);
await Share.shareXFiles( await Share.shareXFiles(
[XFile(filePath)], [XFile(filePath)],
sharePositionOrigin: sharePositionOrigin: Rect.fromLTWH(
Rect.fromLTWH(position.dx, position.dy, 0, 0), position.dx,
position.dy,
size?.width ?? 50,
(size?.height ?? 2) / 2,
),
); );
}, },
), ),
@@ -80,8 +80,8 @@ class StreamGalleryHeader extends StatelessWidget
final galleryHeaderThemeData = StreamGalleryHeaderTheme.of(context); final galleryHeaderThemeData = StreamGalleryHeaderTheme.of(context);
final theme = Theme.of(context); final theme = Theme.of(context);
return AppBar( return AppBar(
toolbarTextStyle: theme.textTheme.bodyText2, toolbarTextStyle: theme.textTheme.bodyMedium,
titleTextStyle: theme.textTheme.headline6, titleTextStyle: theme.textTheme.titleLarge,
systemOverlayStyle: theme.brightness == Brightness.dark systemOverlayStyle: theme.brightness == Brightness.dark
? SystemUiOverlayStyle.light ? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark, : SystemUiOverlayStyle.dark,
@@ -80,7 +80,6 @@ class StreamMessageTextField extends StatefulWidget {
this.textAlignVertical, this.textAlignVertical,
this.textDirection, this.textDirection,
this.readOnly = false, this.readOnly = false,
ToolbarOptions? toolbarOptions,
this.showCursor, this.showCursor,
this.autofocus = false, this.autofocus = false,
this.obscuringCharacter = '', this.obscuringCharacter = '',
@@ -155,31 +154,7 @@ class StreamMessageTextField extends StatefulWidget {
keyboardType = keyboardType ?? keyboardType = keyboardType ??
(maxLines == 1 ? TextInputType.text : TextInputType.multiline), (maxLines == 1 ? TextInputType.text : TextInputType.multiline),
enableInteractiveSelection = enableInteractiveSelection =
enableInteractiveSelection ?? (!readOnly || !obscureText), 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,
)));
/// Controls the message being edited. /// Controls the message being edited.
/// ///
@@ -304,13 +279,6 @@ class StreamMessageTextField extends StatefulWidget {
/// {@macro flutter.widgets.editableText.readOnly} /// {@macro flutter.widgets.editableText.readOnly}
final bool 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} /// {@macro flutter.widgets.editableText.showCursor}
final bool? showCursor; final bool? showCursor;
@@ -720,7 +688,6 @@ class _StreamMessageTextFieldState extends State<StreamMessageTextField>
textAlignVertical: widget.textAlignVertical, textAlignVertical: widget.textAlignVertical,
textDirection: widget.textDirection, textDirection: widget.textDirection,
readOnly: widget.readOnly, readOnly: widget.readOnly,
toolbarOptions: widget.toolbarOptions,
showCursor: widget.showCursor, showCursor: widget.showCursor,
autofocus: widget.autofocus, autofocus: widget.autofocus,
obscuringCharacter: widget.obscuringCharacter, obscuringCharacter: widget.obscuringCharacter,
@@ -107,6 +107,7 @@ class StreamMessageWidget extends StatefulWidget {
this.imageAttachmentThumbnailSize = const Size(400, 400), this.imageAttachmentThumbnailSize = const Size(400, 400),
this.imageAttachmentThumbnailResizeType = 'clip', this.imageAttachmentThumbnailResizeType = 'clip',
this.imageAttachmentThumbnailCropType = 'center', this.imageAttachmentThumbnailCropType = 'center',
this.attachmentActionsModalBuilder,
}) : assert( }) : assert(
bottomRowBuilder == null || bottomRowBuilderWithDefaultWidget == null, bottomRowBuilder == null || bottomRowBuilderWithDefaultWidget == null,
'You can only use one of the two bottom row builders', 'You can only use one of the two bottom row builders',
@@ -144,6 +145,8 @@ class StreamMessageWidget extends StatefulWidget {
imageThumbnailResizeType: imageThumbnailResizeType:
imageAttachmentThumbnailResizeType, imageAttachmentThumbnailResizeType,
imageThumbnailCropType: imageAttachmentThumbnailCropType, imageThumbnailCropType: imageAttachmentThumbnailCropType,
attachmentActionsModalBuilder:
attachmentActionsModalBuilder,
), ),
), ),
attachmentShape: border, attachmentShape: border,
@@ -171,6 +174,7 @@ class StreamMessageWidget extends StatefulWidget {
imageThumbnailSize: imageAttachmentThumbnailSize, imageThumbnailSize: imageAttachmentThumbnailSize,
imageThumbnailResizeType: imageAttachmentThumbnailResizeType, imageThumbnailResizeType: imageAttachmentThumbnailResizeType,
imageThumbnailCropType: imageAttachmentThumbnailCropType, imageThumbnailCropType: imageAttachmentThumbnailCropType,
attachmentActionsModalBuilder: attachmentActionsModalBuilder,
), ),
attachmentShape: border, attachmentShape: border,
); );
@@ -204,6 +208,8 @@ class StreamMessageWidget extends StatefulWidget {
onAttachmentTap(message, attachment); onAttachmentTap(message, attachment);
} }
: null, : null,
attachmentActionsModalBuilder:
attachmentActionsModalBuilder,
); );
}).toList(), }).toList(),
), ),
@@ -533,6 +539,9 @@ class StreamMessageWidget extends StatefulWidget {
/// {@macro onMessageWidgetAttachmentTap} /// {@macro onMessageWidgetAttachmentTap}
final OnMessageWidgetAttachmentTap? onAttachmentTap; final OnMessageWidgetAttachmentTap? onAttachmentTap;
/// {@macro attachmentActionsBuilder}
final AttachmentActionsBuilder? attachmentActionsModalBuilder;
/// Size of the image attachment thumbnail. /// Size of the image attachment thumbnail.
final Size imageAttachmentThumbnailSize; final Size imageAttachmentThumbnailSize;
@@ -617,6 +626,7 @@ class StreamMessageWidget extends StatefulWidget {
Size? imageAttachmentThumbnailSize, Size? imageAttachmentThumbnailSize,
String? imageAttachmentThumbnailResizeType, String? imageAttachmentThumbnailResizeType,
String? imageAttachmentThumbnailCropType, String? imageAttachmentThumbnailCropType,
AttachmentActionsBuilder? attachmentActionsModalBuilder,
}) { }) {
assert( assert(
bottomRowBuilder == null || bottomRowBuilderWithDefaultWidget == null, bottomRowBuilder == null || bottomRowBuilderWithDefaultWidget == null,
@@ -703,6 +713,8 @@ class StreamMessageWidget extends StatefulWidget {
this.imageAttachmentThumbnailResizeType, this.imageAttachmentThumbnailResizeType,
imageAttachmentThumbnailCropType: imageAttachmentThumbnailCropType ?? imageAttachmentThumbnailCropType: imageAttachmentThumbnailCropType ??
this.imageAttachmentThumbnailCropType, this.imageAttachmentThumbnailCropType,
attachmentActionsModalBuilder:
attachmentActionsModalBuilder ?? this.attachmentActionsModalBuilder,
); );
} }
@@ -1088,7 +1088,12 @@ class StreamSvgIcon extends StatelessWidget {
key: key, key: key,
width: width, width: width,
height: height, 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); final theme = Theme.of(context);
return AppBar( return AppBar(
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
toolbarTextStyle: theme.textTheme.bodyText2, toolbarTextStyle: theme.textTheme.bodyMedium,
titleTextStyle: theme.textTheme.headline6, titleTextStyle: theme.textTheme.titleLarge,
systemOverlayStyle: theme.brightness == Brightness.dark systemOverlayStyle: theme.brightness == Brightness.dark
? SystemUiOverlayStyle.light ? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark, : SystemUiOverlayStyle.dark,
@@ -409,7 +409,7 @@ class StreamChannelListErrorWidget extends StatelessWidget {
TextSpan(text: context.translations.loadingChannelsError), TextSpan(text: context.translations.loadingChannelsError),
], ],
), ),
style: Theme.of(context).textTheme.headline6, style: Theme.of(context).textTheme.titleLarge,
), ),
TextButton( TextButton(
onPressed: onPressed, onPressed: onPressed,
@@ -21,6 +21,7 @@ class StreamMessageThemeData with Diagnosticable {
this.avatarTheme, this.avatarTheme,
this.createdAtStyle, this.createdAtStyle,
this.linkBackgroundColor, this.linkBackgroundColor,
this.urlAttachmentTitleMaxLine,
}); });
/// Text style for message text /// Text style for message text
@@ -59,6 +60,9 @@ class StreamMessageThemeData with Diagnosticable {
/// Background color for messages with url attachments. /// Background color for messages with url attachments.
final Color? linkBackgroundColor; final Color? linkBackgroundColor;
/// Max number of lines in Url link title
final int? urlAttachmentTitleMaxLine;
/// Copy with a theme /// Copy with a theme
StreamMessageThemeData copyWith({ StreamMessageThemeData copyWith({
TextStyle? messageTextStyle, TextStyle? messageTextStyle,
@@ -73,6 +77,7 @@ class StreamMessageThemeData with Diagnosticable {
Color? reactionsBorderColor, Color? reactionsBorderColor,
Color? reactionsMaskColor, Color? reactionsMaskColor,
Color? linkBackgroundColor, Color? linkBackgroundColor,
int? urlAttachmentTitleMaxLine,
}) { }) {
return StreamMessageThemeData( return StreamMessageThemeData(
messageTextStyle: messageTextStyle ?? this.messageTextStyle, messageTextStyle: messageTextStyle ?? this.messageTextStyle,
@@ -89,6 +94,8 @@ class StreamMessageThemeData with Diagnosticable {
reactionsBorderColor: reactionsBorderColor ?? this.reactionsBorderColor, reactionsBorderColor: reactionsBorderColor ?? this.reactionsBorderColor,
reactionsMaskColor: reactionsMaskColor ?? this.reactionsMaskColor, reactionsMaskColor: reactionsMaskColor ?? this.reactionsMaskColor,
linkBackgroundColor: linkBackgroundColor ?? this.linkBackgroundColor, linkBackgroundColor: linkBackgroundColor ?? this.linkBackgroundColor,
urlAttachmentTitleMaxLine:
urlAttachmentTitleMaxLine ?? this.urlAttachmentTitleMaxLine,
); );
} }
@@ -148,6 +155,7 @@ class StreamMessageThemeData with Diagnosticable {
reactionsBorderColor: other.reactionsBorderColor, reactionsBorderColor: other.reactionsBorderColor,
reactionsMaskColor: other.reactionsMaskColor, reactionsMaskColor: other.reactionsMaskColor,
linkBackgroundColor: other.linkBackgroundColor, linkBackgroundColor: other.linkBackgroundColor,
urlAttachmentTitleMaxLine: other.urlAttachmentTitleMaxLine,
); );
} }
@@ -167,7 +175,8 @@ class StreamMessageThemeData with Diagnosticable {
reactionsBorderColor == other.reactionsBorderColor && reactionsBorderColor == other.reactionsBorderColor &&
reactionsMaskColor == other.reactionsMaskColor && reactionsMaskColor == other.reactionsMaskColor &&
avatarTheme == other.avatarTheme && avatarTheme == other.avatarTheme &&
linkBackgroundColor == other.linkBackgroundColor; linkBackgroundColor == other.linkBackgroundColor &&
urlAttachmentTitleMaxLine == other.urlAttachmentTitleMaxLine;
@override @override
int get hashCode => int get hashCode =>
@@ -182,7 +191,8 @@ class StreamMessageThemeData with Diagnosticable {
reactionsBorderColor.hashCode ^ reactionsBorderColor.hashCode ^
reactionsMaskColor.hashCode ^ reactionsMaskColor.hashCode ^
avatarTheme.hashCode ^ avatarTheme.hashCode ^
linkBackgroundColor.hashCode; linkBackgroundColor.hashCode ^
urlAttachmentTitleMaxLine.hashCode;
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
@@ -199,6 +209,10 @@ class StreamMessageThemeData with Diagnosticable {
..add(ColorProperty('reactionsBackgroundColor', reactionsBackgroundColor)) ..add(ColorProperty('reactionsBackgroundColor', reactionsBackgroundColor))
..add(ColorProperty('reactionsBorderColor', reactionsBorderColor)) ..add(ColorProperty('reactionsBorderColor', reactionsBorderColor))
..add(ColorProperty('reactionsMaskColor', reactionsMaskColor)) ..add(ColorProperty('reactionsMaskColor', reactionsMaskColor))
..add(ColorProperty('linkBackgroundColor', linkBackgroundColor)); ..add(ColorProperty('linkBackgroundColor', linkBackgroundColor))
..add(DiagnosticsProperty(
'urlAttachmentTitleMaxLine',
urlAttachmentTitleMaxLine,
));
} }
} }
@@ -1,6 +1,6 @@
import 'package:stream_chat_flutter/src/video/vlc/vlc_stub.dart' import 'package:stream_chat_flutter/src/video/vlc/vlc_stub.dart'
if (dart.library.io) 'vlc_manager_desktop.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} /// {@template vlcManager}
/// An abstract class for the purpose of ensuring Flutter applications that /// An abstract class for the purpose of ensuring Flutter applications that
+8 -10
View File
@@ -12,12 +12,11 @@ environment:
dependencies: dependencies:
cached_network_image: ^3.0.0 cached_network_image: ^3.0.0
chewie: ^1.3.4 chewie: ^1.3.4
collection: ^1.15.0 collection: ^1.17.0
contextmenu: ^3.0.0 contextmenu: ^3.0.0
dart_vlc: ^0.4.0 dart_vlc: ^0.4.0
desktop_drop: ^0.4.0 desktop_drop: ^0.4.0
diacritic: ^0.1.3 diacritic: ^0.1.3
dio: ^4.0.6
ezanimation: ^0.6.0 ezanimation: ^0.6.0
file_picker: ^5.2.4 file_picker: ^5.2.4
file_selector: ^0.9.0 file_selector: ^0.9.0
@@ -25,26 +24,25 @@ dependencies:
sdk: flutter sdk: flutter
flutter_markdown: ^0.6.1 flutter_markdown: ^0.6.1
flutter_portal: ^1.0.0 flutter_portal: ^1.0.0
flutter_svg: ^1.0.1 flutter_svg: ^2.0.4
http: ^0.13.4
http_parser: ^4.0.0 http_parser: ^4.0.0
image_gallery_saver: ^1.7.1 image_gallery_saver: ^1.7.1
image_picker: ^0.8.2 image_picker: ^0.8.2
jiffy: ^5.0.0 jiffy: ^5.0.0
lottie: ^2.0.0 lottie: ^2.0.0
meta: ^1.3.0 meta: ^1.8.0
path_provider: ^2.0.9 path_provider: ^2.0.9
photo_manager: ^2.5.2 photo_manager: ^2.5.2
photo_view: ^0.14.0 photo_view: ^0.14.0
rxdart: ^0.27.0 rxdart: ^0.27.0
share_plus: ^4.5.0 share_plus: ^6.3.0
shimmer: ^2.0.0 shimmer: ^2.0.0
stream_chat_flutter_core: ^5.3.0 stream_chat_flutter_core: ^5.3.0
synchronized: ^3.0.0 synchronized: ^3.0.0
thumblr: ^0.0.4 thumblr: ^0.0.4
url_launcher: ^6.1.0 url_launcher: ^6.1.0
video_player: ^2.4.5 video_player: ^2.4.5
video_player_macos: ^1.0.6 video_player_macos: ^2.0.1
video_thumbnail: ^0.5.0 video_thumbnail: ^0.5.0
flutter: flutter:
@@ -56,9 +54,9 @@ flutter:
uses-material-design: true uses-material-design: true
dev_dependencies: dev_dependencies:
dart_code_metrics: ^4.4.0 dart_code_metrics: ^5.7.0
flutter_test: flutter_test:
sdk: flutter sdk: flutter
golden_toolkit: ^0.13.0 golden_toolkit: ^0.15.0
mocktail: ^0.3.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 ## 5.3.0
- Updated `stream_chat` dependency to [`5.3.0`](https://pub.dev/packages/stream_chat/changelog). - 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: environment:
sdk: '>=2.17.0 <3.0.0' sdk: '>=2.17.0 <3.0.0'
flutter: ">=1.17.0"
dependencies: dependencies:
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
@@ -27,6 +28,7 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
stream_chat_flutter_core: ^5.1.0 stream_chat_flutter_core: ^5.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
@@ -6,7 +6,7 @@
#include "generated_plugin_registrant.h" #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) { void RegisterPlugins(flutter::PluginRegistry* registry) {
ConnectivityPlusWindowsPluginRegisterWithRegistrar( ConnectivityPlusWindowsPluginRegisterWithRegistrar(
@@ -3,7 +3,7 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
connectivity_plus_windows connectivity_plus
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
@@ -83,7 +83,7 @@ abstract class PagedValueNotifier<Key, Value>
/// Paged value that can be used with [PagedValueNotifier]. /// Paged value that can be used with [PagedValueNotifier].
@freezed @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] /// Represents the success state of the [PagedValue]
// @Assert( // @Assert(
// 'nextPageKey != null', // 'nextPageKey != null',
@@ -1,7 +1,7 @@
// coverage:ignore-file // coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint // 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'; part of 'paged_value_notifier.dart';
@@ -27,11 +27,11 @@ mixin _$PagedValue<Key, Value> {
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>( TResult? whenOrNull<TResult extends Object?>(
TResult Function( TResult? Function(
List<Value> items, Key? nextPageKey, StreamChatError? error)? List<Value> items, Key? nextPageKey, StreamChatError? error)?
$default, { $default, {
TResult Function()? loading, TResult? Function()? loading,
TResult Function(StreamChatError error)? error, TResult? Function(StreamChatError error)? error,
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
@@ -53,9 +53,9 @@ mixin _$PagedValue<Key, Value> {
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>( TResult? mapOrNull<TResult extends Object?>(
TResult Function(Success<Key, Value> value)? $default, { TResult? Function(Success<Key, Value> value)? $default, {
TResult Function(Loading<Key, Value> value)? loading, TResult? Function(Loading<Key, Value> value)? loading,
TResult Function(Error<Key, Value> value)? error, TResult? Function(Error<Key, Value> value)? error,
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
@@ -72,17 +72,19 @@ mixin _$PagedValue<Key, Value> {
abstract class $PagedValueCopyWith<Key, Value, $Res> { abstract class $PagedValueCopyWith<Key, Value, $Res> {
factory $PagedValueCopyWith(PagedValue<Key, Value> value, factory $PagedValueCopyWith(PagedValue<Key, Value> value,
$Res Function(PagedValue<Key, Value>) then) = $Res Function(PagedValue<Key, Value>) then) =
_$PagedValueCopyWithImpl<Key, Value, $Res>; _$PagedValueCopyWithImpl<Key, Value, $Res, PagedValue<Key, Value>>;
} }
/// @nodoc /// @nodoc
class _$PagedValueCopyWithImpl<Key, Value, $Res> class _$PagedValueCopyWithImpl<Key, Value, $Res,
$Val extends PagedValue<Key, Value>>
implements $PagedValueCopyWith<Key, Value, $Res> { implements $PagedValueCopyWith<Key, Value, $Res> {
_$PagedValueCopyWithImpl(this._value, this._then); _$PagedValueCopyWithImpl(this._value, this._then);
final PagedValue<Key, Value> _value;
// ignore: unused_field // ignore: unused_field
final $Res Function(PagedValue<Key, Value>) _then; final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
} }
/// @nodoc /// @nodoc
@@ -90,36 +92,35 @@ abstract class _$$SuccessCopyWith<Key, Value, $Res> {
factory _$$SuccessCopyWith(_$Success<Key, Value> value, factory _$$SuccessCopyWith(_$Success<Key, Value> value,
$Res Function(_$Success<Key, Value>) then) = $Res Function(_$Success<Key, Value>) then) =
__$$SuccessCopyWithImpl<Key, Value, $Res>; __$$SuccessCopyWithImpl<Key, Value, $Res>;
@useResult
$Res call({List<Value> items, Key? nextPageKey, StreamChatError? error}); $Res call({List<Value> items, Key? nextPageKey, StreamChatError? error});
} }
/// @nodoc /// @nodoc
class __$$SuccessCopyWithImpl<Key, Value, $Res> class __$$SuccessCopyWithImpl<Key, Value, $Res>
extends _$PagedValueCopyWithImpl<Key, Value, $Res> extends _$PagedValueCopyWithImpl<Key, Value, $Res, _$Success<Key, Value>>
implements _$$SuccessCopyWith<Key, Value, $Res> { implements _$$SuccessCopyWith<Key, Value, $Res> {
__$$SuccessCopyWithImpl( __$$SuccessCopyWithImpl(
_$Success<Key, Value> _value, $Res Function(_$Success<Key, Value>) _then) _$Success<Key, Value> _value, $Res Function(_$Success<Key, Value>) _then)
: super(_value, (v) => _then(v as _$Success<Key, Value>)); : super(_value, _then);
@override
_$Success<Key, Value> get _value => super._value as _$Success<Key, Value>;
@pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? items = freezed, Object? items = null,
Object? nextPageKey = freezed, Object? nextPageKey = freezed,
Object? error = freezed, Object? error = freezed,
}) { }) {
return _then(_$Success<Key, Value>( return _then(_$Success<Key, Value>(
items: items == freezed items: null == items
? _value._items ? _value._items
: items // ignore: cast_nullable_to_non_nullable : items // ignore: cast_nullable_to_non_nullable
as List<Value>, as List<Value>,
nextPageKey: nextPageKey == freezed nextPageKey: freezed == nextPageKey
? _value.nextPageKey ? _value.nextPageKey
: nextPageKey // ignore: cast_nullable_to_non_nullable : nextPageKey // ignore: cast_nullable_to_non_nullable
as Key?, as Key?,
error: error == freezed error: freezed == error
? _value.error ? _value.error
: error // ignore: cast_nullable_to_non_nullable : error // ignore: cast_nullable_to_non_nullable
as StreamChatError?, as StreamChatError?,
@@ -142,6 +143,7 @@ class _$Success<Key, Value> extends Success<Key, Value>
/// List with all items loaded so far. /// List with all items loaded so far.
@override @override
List<Value> get items { List<Value> get items {
if (_items is EqualUnmodifiableListView) return _items;
// ignore: implicit_dynamic_type // ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_items); 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._items, _items) &&
const DeepCollectionEquality() const DeepCollectionEquality()
.equals(other.nextPageKey, nextPageKey) && .equals(other.nextPageKey, nextPageKey) &&
const DeepCollectionEquality().equals(other.error, error)); (identical(other.error, error) || other.error == error));
} }
@override @override
@@ -185,10 +187,11 @@ class _$Success<Key, Value> extends Success<Key, Value>
runtimeType, runtimeType,
const DeepCollectionEquality().hash(_items), const DeepCollectionEquality().hash(_items),
const DeepCollectionEquality().hash(nextPageKey), const DeepCollectionEquality().hash(nextPageKey),
const DeepCollectionEquality().hash(error)); error);
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@pragma('vm:prefer-inline')
_$$SuccessCopyWith<Key, Value, _$Success<Key, Value>> get copyWith => _$$SuccessCopyWith<Key, Value, _$Success<Key, Value>> get copyWith =>
__$$SuccessCopyWithImpl<Key, Value, _$Success<Key, Value>>( __$$SuccessCopyWithImpl<Key, Value, _$Success<Key, Value>>(
this, _$identity); this, _$identity);
@@ -208,11 +211,11 @@ class _$Success<Key, Value> extends Success<Key, Value>
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>( TResult? whenOrNull<TResult extends Object?>(
TResult Function( TResult? Function(
List<Value> items, Key? nextPageKey, StreamChatError? error)? List<Value> items, Key? nextPageKey, StreamChatError? error)?
$default, { $default, {
TResult Function()? loading, TResult? Function()? loading,
TResult Function(StreamChatError error)? error, TResult? Function(StreamChatError error)? error,
}) { }) {
return $default?.call(items, nextPageKey, this.error); return $default?.call(items, nextPageKey, this.error);
} }
@@ -246,9 +249,9 @@ class _$Success<Key, Value> extends Success<Key, Value>
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>( TResult? mapOrNull<TResult extends Object?>(
TResult Function(Success<Key, Value> value)? $default, { TResult? Function(Success<Key, Value> value)? $default, {
TResult Function(Loading<Key, Value> value)? loading, TResult? Function(Loading<Key, Value> value)? loading,
TResult Function(Error<Key, Value> value)? error, TResult? Function(Error<Key, Value> value)? error,
}) { }) {
return $default?.call(this); return $default?.call(this);
} }
@@ -276,13 +279,13 @@ abstract class Success<Key, Value> extends PagedValue<Key, Value> {
const Success._() : super._(); const Success._() : super._();
/// List with all items loaded so far. /// 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. /// The key for the next page to be fetched.
Key? get nextPageKey => throw _privateConstructorUsedError; Key? get nextPageKey;
/// The current error, if any. /// The current error, if any.
StreamChatError? get error => throw _privateConstructorUsedError; StreamChatError? get error;
@JsonKey(ignore: true) @JsonKey(ignore: true)
_$$SuccessCopyWith<Key, Value, _$Success<Key, Value>> get copyWith => _$$SuccessCopyWith<Key, Value, _$Success<Key, Value>> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@@ -297,14 +300,11 @@ abstract class _$$LoadingCopyWith<Key, Value, $Res> {
/// @nodoc /// @nodoc
class __$$LoadingCopyWithImpl<Key, Value, $Res> class __$$LoadingCopyWithImpl<Key, Value, $Res>
extends _$PagedValueCopyWithImpl<Key, Value, $Res> extends _$PagedValueCopyWithImpl<Key, Value, $Res, _$Loading<Key, Value>>
implements _$$LoadingCopyWith<Key, Value, $Res> { implements _$$LoadingCopyWith<Key, Value, $Res> {
__$$LoadingCopyWithImpl( __$$LoadingCopyWithImpl(
_$Loading<Key, Value> _value, $Res Function(_$Loading<Key, Value>) _then) _$Loading<Key, Value> _value, $Res Function(_$Loading<Key, Value>) _then)
: super(_value, (v) => _then(v as _$Loading<Key, Value>)); : super(_value, _then);
@override
_$Loading<Key, Value> get _value => super._value as _$Loading<Key, Value>;
} }
/// @nodoc /// @nodoc
@@ -349,11 +349,11 @@ class _$Loading<Key, Value> extends Loading<Key, Value>
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>( TResult? whenOrNull<TResult extends Object?>(
TResult Function( TResult? Function(
List<Value> items, Key? nextPageKey, StreamChatError? error)? List<Value> items, Key? nextPageKey, StreamChatError? error)?
$default, { $default, {
TResult Function()? loading, TResult? Function()? loading,
TResult Function(StreamChatError error)? error, TResult? Function(StreamChatError error)? error,
}) { }) {
return loading?.call(); return loading?.call();
} }
@@ -387,9 +387,9 @@ class _$Loading<Key, Value> extends Loading<Key, Value>
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>( TResult? mapOrNull<TResult extends Object?>(
TResult Function(Success<Key, Value> value)? $default, { TResult? Function(Success<Key, Value> value)? $default, {
TResult Function(Loading<Key, Value> value)? loading, TResult? Function(Loading<Key, Value> value)? loading,
TResult Function(Error<Key, Value> value)? error, TResult? Function(Error<Key, Value> value)? error,
}) { }) {
return loading?.call(this); return loading?.call(this);
} }
@@ -419,26 +419,25 @@ abstract class _$$ErrorCopyWith<Key, Value, $Res> {
factory _$$ErrorCopyWith( factory _$$ErrorCopyWith(
_$Error<Key, Value> value, $Res Function(_$Error<Key, Value>) then) = _$Error<Key, Value> value, $Res Function(_$Error<Key, Value>) then) =
__$$ErrorCopyWithImpl<Key, Value, $Res>; __$$ErrorCopyWithImpl<Key, Value, $Res>;
@useResult
$Res call({StreamChatError error}); $Res call({StreamChatError error});
} }
/// @nodoc /// @nodoc
class __$$ErrorCopyWithImpl<Key, Value, $Res> class __$$ErrorCopyWithImpl<Key, Value, $Res>
extends _$PagedValueCopyWithImpl<Key, Value, $Res> extends _$PagedValueCopyWithImpl<Key, Value, $Res, _$Error<Key, Value>>
implements _$$ErrorCopyWith<Key, Value, $Res> { implements _$$ErrorCopyWith<Key, Value, $Res> {
__$$ErrorCopyWithImpl( __$$ErrorCopyWithImpl(
_$Error<Key, Value> _value, $Res Function(_$Error<Key, Value>) _then) _$Error<Key, Value> _value, $Res Function(_$Error<Key, Value>) _then)
: super(_value, (v) => _then(v as _$Error<Key, Value>)); : super(_value, _then);
@override
_$Error<Key, Value> get _value => super._value as _$Error<Key, Value>;
@pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? error = freezed, Object? error = null,
}) { }) {
return _then(_$Error<Key, Value>( return _then(_$Error<Key, Value>(
error == freezed null == error
? _value.error ? _value.error
: error // ignore: cast_nullable_to_non_nullable : error // ignore: cast_nullable_to_non_nullable
as StreamChatError, as StreamChatError,
@@ -473,15 +472,15 @@ class _$Error<Key, Value> extends Error<Key, Value>
return identical(this, other) || return identical(this, other) ||
(other.runtimeType == runtimeType && (other.runtimeType == runtimeType &&
other is _$Error<Key, Value> && other is _$Error<Key, Value> &&
const DeepCollectionEquality().equals(other.error, error)); (identical(other.error, error) || other.error == error));
} }
@override @override
int get hashCode => int get hashCode => Object.hash(runtimeType, error);
Object.hash(runtimeType, const DeepCollectionEquality().hash(error));
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@pragma('vm:prefer-inline')
_$$ErrorCopyWith<Key, Value, _$Error<Key, Value>> get copyWith => _$$ErrorCopyWith<Key, Value, _$Error<Key, Value>> get copyWith =>
__$$ErrorCopyWithImpl<Key, Value, _$Error<Key, Value>>(this, _$identity); __$$ErrorCopyWithImpl<Key, Value, _$Error<Key, Value>>(this, _$identity);
@@ -500,11 +499,11 @@ class _$Error<Key, Value> extends Error<Key, Value>
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>( TResult? whenOrNull<TResult extends Object?>(
TResult Function( TResult? Function(
List<Value> items, Key? nextPageKey, StreamChatError? error)? List<Value> items, Key? nextPageKey, StreamChatError? error)?
$default, { $default, {
TResult Function()? loading, TResult? Function()? loading,
TResult Function(StreamChatError error)? error, TResult? Function(StreamChatError error)? error,
}) { }) {
return error?.call(this.error); return error?.call(this.error);
} }
@@ -538,9 +537,9 @@ class _$Error<Key, Value> extends Error<Key, Value>
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>( TResult? mapOrNull<TResult extends Object?>(
TResult Function(Success<Key, Value> value)? $default, { TResult? Function(Success<Key, Value> value)? $default, {
TResult Function(Loading<Key, Value> value)? loading, TResult? Function(Loading<Key, Value> value)? loading,
TResult Function(Error<Key, Value> value)? error, TResult? Function(Error<Key, Value> value)? error,
}) { }) {
return error?.call(this); 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 factory Error(final StreamChatError error) = _$Error<Key, Value>;
const Error._() : super._(); const Error._() : super._();
StreamChatError get error => throw _privateConstructorUsedError; StreamChatError get error;
@JsonKey(ignore: true) @JsonKey(ignore: true)
_$$ErrorCopyWith<Key, Value, _$Error<Key, Value>> get copyWith => _$$ErrorCopyWith<Key, Value, _$Error<Key, Value>> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@@ -425,8 +425,8 @@ class StreamChannelState extends State<StreamChannel> {
var message = snapshot.error.toString(); var message = snapshot.error.toString();
if (snapshot.error is DioError) { if (snapshot.error is DioError) {
final dioError = snapshot.error as DioError?; final dioError = snapshot.error as DioError?;
if (dioError?.type == DioErrorType.response) { if (dioError?.type == DioErrorType.badResponse) {
message = dioError!.message; message = dioError!.message ?? 'Bad response';
} else { } else {
message = 'Check your connection and retry'; message = 'Check your connection and retry';
} }
@@ -244,10 +244,11 @@ class StreamChannelListController extends PagedValueNotifier<int, Channel> {
_unsubscribeFromChannelListEvents(); _unsubscribeFromChannelListEvents();
} }
_channelEventSubscription = _channelEventSubscription = client
client.on().skip(1) // Skipping the last emitted event. .on()
// We only need to handle the latest events. .skip(1) // Skipping the last emitted event.
.listen((event) { // We only need to handle the latest events.
.listen((event) {
// Only handle the event if the value is in success state. // Only handle the event if the value is in success state.
if (value.isNotSuccess) return; if (value.isNotSuccess) return;
@@ -10,20 +10,21 @@ environment:
flutter: ">=1.17.0" flutter: ">=1.17.0"
dependencies: dependencies:
collection: ^1.15.0 collection: ^1.17.0
connectivity_plus: ^3.0.2 connectivity_plus: ^3.0.2
flutter: flutter:
sdk: flutter sdk: flutter
freezed_annotation: ^2.0.3 freezed_annotation: ^2.0.3
meta: ^1.3.0 meta: ^1.8.0
rxdart: ^0.27.0 rxdart: ^0.27.0
stream_chat: ^5.3.0 stream_chat: ^5.3.0
dev_dependencies: dev_dependencies:
build_runner: ^2.0.1 build_runner: ^2.3.3
dart_code_metrics: ^4.4.0 dart_code_metrics: ^5.7.0
fake_async: ^1.2.0 fake_async: ^1.2.0
flutter_test: flutter_test:
sdk: flutter sdk: flutter
freezed: ^2.0.3 freezed: ^2.3.2
mocktail: ^0.3.0 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!'; const errorMessage = 'Error! Error! Error!';
final error = DioError( final error = DioError(
type: DioErrorType.response, type: DioErrorType.badResponse,
error: errorMessage, message: errorMessage,
requestOptions: RequestOptions(path: ''), requestOptions: RequestOptions(),
); );
when(() => mockChannel.initialized) when(() => mockChannel.initialized)
.thenAnswer((_) => Future.error(error)); .thenAnswer((_) => Future.error(error));
@@ -15,6 +15,7 @@ dependencies:
flutter_localizations: flutter_localizations:
sdk: flutter sdk: flutter
stream_chat_flutter: ^5.3.0 stream_chat_flutter: ^5.3.0
dev_dependencies: dev_dependencies:
dart_code_metrics: ^4.16.0 dart_code_metrics: ^4.16.0
flutter_test: flutter_test:
@@ -103,7 +103,7 @@ class LocalizationTrackerState extends State<LocalizationTracker> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
captionFontSize = Theme.of(context).textTheme.caption!.fontSize!; captionFontSize = Theme.of(context).textTheme.bodySmall!.fontSize!;
return Container(); return Container();
} }
} }
@@ -1,3 +1,7 @@
## Upcoming
- Updated dependencies to resolvable versions.
## 5.1.0 ## 5.1.0
- Reintroduce support for experimental indexedDB on Web. - Reintroduce support for experimental indexedDB on Web.
@@ -6,6 +6,7 @@ version: 1.0.0+1
environment: environment:
sdk: '>=2.17.0 <3.0.0' sdk: '>=2.17.0 <3.0.0'
flutter: ">=1.17.0"
dependencies: dependencies:
cupertino_icons: ^1.0.3 cupertino_icons: ^1.0.3
@@ -13,6 +14,7 @@ dependencies:
sdk: flutter sdk: flutter
stream_chat: ^5.1.0 stream_chat: ^5.1.0
stream_chat_persistence: ^5.1.0 stream_chat_persistence: ^5.1.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
@@ -10,20 +10,21 @@ environment:
flutter: ">=1.17.0" flutter: ">=1.17.0"
dependencies: dependencies:
drift: ^1.5.0 drift: ^1.7.1
flutter: flutter:
sdk: flutter sdk: flutter
logging: ^1.0.1 logging: ^1.0.1
meta: ^1.3.0 meta: ^1.8.0
mutex: ^3.0.0 mutex: ^3.0.0
path: ^1.8.0 path: ^1.8.2
path_provider: ^2.0.1 path_provider: ^2.0.1
sqlite3_flutter_libs: ^0.5.0 sqlite3_flutter_libs: ^0.5.0
stream_chat: ^5.1.0 stream_chat: ^5.1.0
dev_dependencies: dev_dependencies:
build_runner: ^2.0.1 build_runner: ^2.3.3
dart_code_metrics: ^4.4.0 dart_code_metrics: ^4.18.0
drift_dev: ^1.5.2 drift_dev: ^1.7.1
flutter_test: flutter_test:
sdk: flutter sdk: flutter
mocktail: ^0.3.0 mocktail: ^0.3.0
+7
View File
@@ -0,0 +1,7 @@
name: stream_chat_flutter_workspace
environment:
sdk: '>=2.18.0 <3.0.0'
dev_dependencies:
melos: ^3.0.0