Merge pull request #1732 from GetStream/release/v6.10.0

This commit is contained in:
Sahil Kumar
2023-09-11 15:13:58 +05:30
committed by GitHub
29 changed files with 225 additions and 156 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
name: Publish docusaurus docs name: Publish docusaurus docs
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Setup Node 16 - name: Setup Node 16
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
+1 -1
View File
@@ -37,7 +37,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: "Git Checkout" - name: "Git Checkout"
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
+5 -5
View File
@@ -23,7 +23,7 @@ jobs:
stream_chat: stream_chat:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: axel-op/dart-package-analyzer@v3 - uses: axel-op/dart-package-analyzer@v3
id: analysis id: analysis
with: with:
@@ -43,7 +43,7 @@ jobs:
stream_chat_persistence: stream_chat_persistence:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: axel-op/dart-package-analyzer@v3 - uses: axel-op/dart-package-analyzer@v3
id: analysis id: analysis
with: with:
@@ -64,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@v3 - uses: actions/checkout@v4
- uses: axel-op/dart-package-analyzer@v3 - uses: axel-op/dart-package-analyzer@v3
id: analysis id: analysis
with: with:
@@ -84,7 +84,7 @@ jobs:
stream_chat_flutter: stream_chat_flutter:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: axel-op/dart-package-analyzer@v3 - uses: axel-op/dart-package-analyzer@v3
id: analysis id: analysis
with: with:
@@ -104,7 +104,7 @@ jobs:
stream_chat_localizations: stream_chat_localizations:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: axel-op/dart-package-analyzer@v3 - uses: axel-op/dart-package-analyzer@v3
id: analysis id: analysis
with: with:
@@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: "Git Checkout" - name: "Git Checkout"
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: "Install Flutter" - name: "Install Flutter"
@@ -57,14 +57,14 @@ jobs:
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- name: "Git Checkout" - name: "Git Checkout"
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: "Install Flutter" - name: "Install Flutter"
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
cache: true cache: true
flutter-version: ${{ env.flutter_version }} channel: ${{ env.flutter_channel }}
- name: "Install Tools" - name: "Install Tools"
run: | run: |
flutter pub global activate melos flutter pub global activate melos
@@ -82,14 +82,14 @@ jobs:
timeout-minutes: 30 timeout-minutes: 30
steps: steps:
- name: "Git Checkout" - name: "Git Checkout"
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: "Install Flutter" - name: "Install Flutter"
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
cache: true cache: true
flutter-version: ${{ env.flutter_version }} channel: ${{ env.flutter_channel }}
- name: "Install Tools" - name: "Install Tools"
run: | run: |
flutter pub global activate melos flutter pub global activate melos
+1 -1
View File
@@ -7,7 +7,7 @@ jobs:
name: Vale doc linter name: Vale doc linter
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: errata-ai/vale-action@reviewdog - uses: errata-ai/vale-action@reviewdog
with: with:
# added, diff_context, file, nofilter # added, diff_context, file, nofilter
+9
View File
@@ -1,3 +1,12 @@
## 6.9.0
🐞 Fixed
- [[#1716]](https://github.com/GetStream/stream-chat-flutter/issues/1716) Fixed client not able to
update message with `type: reply`.
- [[#1724]](https://github.com/GetStream/stream-chat-flutter/issues/1724) Fixed sendFile error
on `AttachmentFile` with `bytes` and no `name`.
## 6.8.0 ## 6.8.0
🐞 Fixed 🐞 Fixed
@@ -74,13 +74,13 @@ class AttachmentFile {
if (CurrentPlatform.isWeb) { if (CurrentPlatform.isWeb) {
multiPartFile = MultipartFile.fromBytes( multiPartFile = MultipartFile.fromBytes(
bytes!, bytes!,
filename: name, filename: name ?? 'file',
contentType: mimeType, contentType: mimeType,
); );
} else { } else {
multiPartFile = await MultipartFile.fromFile( multiPartFile = await MultipartFile.fromFile(
path!, path!,
filename: name, filename: name ?? 'file',
contentType: mimeType, contentType: mimeType,
); );
} }
@@ -168,8 +168,16 @@ class Message extends Equatable {
late final MessageState state; late final MessageState state;
/// The message type. /// The message type.
@JsonKey(includeIfNull: false, toJson: _typeToJson)
final String type; final String type;
// We need to skip passing type if it's not regular or system as the API
// does not expect it.
static String? _typeToJson(String type) {
if (['regular', 'system'].contains(type)) return type;
return null;
}
/// 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
/// command or as a result of URL scraping. /// command or as a result of URL scraping.
@JsonKey(includeIfNull: false) @JsonKey(includeIfNull: false)
@@ -71,17 +71,27 @@ Message _$MessageFromJson(Map<String, dynamic> json) => Message(
), ),
); );
Map<String, dynamic> _$MessageToJson(Message instance) => <String, dynamic>{ Map<String, dynamic> _$MessageToJson(Message instance) {
'id': instance.id, final val = <String, dynamic>{
'text': instance.text, 'id': instance.id,
'type': instance.type, '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', Message._typeToJson(instance.type));
}; val['attachments'] = instance.attachments.map((e) => e.toJson()).toList();
val['mentioned_users'] = User.toIds(instance.mentionedUsers);
val['parent_id'] = instance.parentId;
val['quoted_message_id'] = instance.quotedMessageId;
val['show_in_channel'] = instance.showInChannel;
val['silent'] = instance.silent;
val['pinned'] = instance.pinned;
val['pin_expires'] = instance.pinExpires?.toIso8601String();
val['extra_data'] = instance.extraData;
return val;
}
+1 -1
View File
@@ -3,4 +3,4 @@ import 'package:stream_chat/src/client/client.dart';
/// Current package version /// Current package version
/// Used in [StreamChatClient] to build the `x-stream-client` header /// Used in [StreamChatClient] to build the `x-stream-client` header
// ignore: constant_identifier_names // ignore: constant_identifier_names
const PACKAGE_VERSION = '6.8.0'; const PACKAGE_VERSION = '6.9.0';
+1 -1
View File
@@ -1,7 +1,7 @@
name: stream_chat name: stream_chat
homepage: https://getstream.io/ homepage: https://getstream.io/
description: The official Dart client for Stream Chat, a service for building chat applications. description: The official Dart client for Stream Chat, a service for building chat applications.
version: 6.8.0 version: 6.9.0
repository: https://github.com/GetStream/stream-chat-flutter repository: https://github.com/GetStream/stream-chat-flutter
issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
+15 -1
View File
@@ -1,3 +1,16 @@
## 6.10.0
🐞 Fixed
- [[#1721]](https://github.com/GetStream/stream-chat-flutter/issues/1721)
Fixed `StreamMessageInput.allowedAttachmentPickerTypes` not working on mobile devices.
✅ Added
- Added support for overriding the `MessageWidget.onReactionsHover` callback.
> **Note**
> Used only in desktop devices (web and desktop).
## 6.9.0 ## 6.9.0
🐞 Fixed 🐞 Fixed
@@ -11,7 +24,8 @@
- Added support for listening error events in AttachmentPickerBottomSheet. - Added support for listening error events in AttachmentPickerBottomSheet.
- Added support for overriding the `MessageWidget.onReactionTap` callback. - Added support for overriding the `MessageWidget.onReactionTap` callback.
- Added support for `StreamMessageInput.contentInsertionConfiguration` to specify the content insertion configuration. - Added support for `StreamMessageInput.contentInsertionConfiguration` to specify the content
insertion configuration.
[#1613](https://github.com/GetStream/stream-chat-flutter/issues/1613) [#1613](https://github.com/GetStream/stream-chat-flutter/issues/1613)
```dart ```dart
@@ -159,7 +159,6 @@
C4CD72858CD59598795BB48E /* Pods-Runner.release.xcconfig */, C4CD72858CD59598795BB48E /* Pods-Runner.release.xcconfig */,
2BCA7399119839DE435DACD6 /* Pods-Runner.profile.xcconfig */, 2BCA7399119839DE435DACD6 /* Pods-Runner.profile.xcconfig */,
); );
name = Pods;
path = Pods; path = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@@ -203,7 +202,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 0920; LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1300; LastUpgradeCheck = 1430;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
33CC10EC2044A3C60003C045 = { 33CC10EC2044A3C60003C045 = {
@@ -427,7 +426,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.15; MACOSX_DEPLOYMENT_TARGET = 11.0;
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
}; };
@@ -554,7 +553,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.15; MACOSX_DEPLOYMENT_TARGET = 11.0;
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@@ -575,7 +574,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.15; MACOSX_DEPLOYMENT_TARGET = 11.0;
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
}; };
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1300" LastUpgradeVersion = "1430"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@@ -799,7 +799,7 @@ Widget mobileAttachmentPickerBuilder({
); );
}, },
), ),
}..where((option) => option.supportedTypes.every(allowedTypes.contains)), }.where((option) => option.supportedTypes.every(allowedTypes.contains)),
}, },
); );
} }
@@ -56,6 +56,7 @@ class StreamMessageWidget extends StatefulWidget {
this.onMentionTap, this.onMentionTap,
this.onMessageTap, this.onMessageTap,
this.onReactionsTap, this.onReactionsTap,
this.onReactionsHover,
bool? showReactionPicker, bool? showReactionPicker,
@Deprecated('Use `showReactionPicker` instead') @Deprecated('Use `showReactionPicker` instead')
bool showReactionPickerIndicator = true, bool showReactionPickerIndicator = true,
@@ -474,7 +475,8 @@ class StreamMessageWidget extends StatefulWidget {
/// {@template showReactionPickerIndicator} /// {@template showReactionPickerIndicator}
/// Used in [StreamMessageReactionsModal] and [MessageActionsModal] /// Used in [StreamMessageReactionsModal] and [MessageActionsModal]
/// {@endtemplate} @Deprecated('Use `showReactionPicker` instead') /// {@endtemplate}
@Deprecated('Use `showReactionPicker` instead')
bool get showReactionPickerIndicator => showReactionPicker; bool get showReactionPickerIndicator => showReactionPicker;
/// {@template showReactionPickerTail} /// {@template showReactionPickerTail}
@@ -565,8 +567,16 @@ class StreamMessageWidget extends StatefulWidget {
final void Function(Message)? onMessageTap; final void Function(Message)? onMessageTap;
/// {@macro onReactionsTap} /// {@macro onReactionsTap}
///
/// Note: Only used in mobile devices (iOS and Android). Do not confuse this
/// with the tap action on the reactions picker.
final OnReactionsTap? onReactionsTap; final OnReactionsTap? onReactionsTap;
/// {@template onReactionsHover}
///
/// Note: Only used in desktop devices (web and desktop).
final OnReactionsHover? onReactionsHover;
/// {@template customActions} /// {@template customActions}
/// List of custom actions shown on message long tap /// List of custom actions shown on message long tap
/// {@endtemplate} /// {@endtemplate}
@@ -640,6 +650,7 @@ class StreamMessageWidget extends StatefulWidget {
bool? showInChannelIndicator, bool? showInChannelIndicator,
void Function(User)? onUserAvatarTap, void Function(User)? onUserAvatarTap,
void Function(String)? onLinkTap, void Function(String)? onLinkTap,
bool? showReactionBrowser,
bool? showReactionPicker, bool? showReactionPicker,
@Deprecated('Use `showReactionPicker` instead') @Deprecated('Use `showReactionPicker` instead')
bool? showReactionPickerIndicator, bool? showReactionPickerIndicator,
@@ -662,6 +673,7 @@ class StreamMessageWidget extends StatefulWidget {
OnQuotedMessageTap? onQuotedMessageTap, OnQuotedMessageTap? onQuotedMessageTap,
void Function(Message)? onMessageTap, void Function(Message)? onMessageTap,
OnReactionsTap? onReactionsTap, OnReactionsTap? onReactionsTap,
OnReactionsHover? onReactionsHover,
List<StreamMessageAction>? customActions, List<StreamMessageAction>? customActions,
void Function(Message message, Attachment attachment)? onAttachmentTap, void Function(Message message, Attachment attachment)? onAttachmentTap,
Widget Function(BuildContext, User)? userAvatarBuilder, Widget Function(BuildContext, User)? userAvatarBuilder,
@@ -752,6 +764,7 @@ class StreamMessageWidget extends StatefulWidget {
onQuotedMessageTap: onQuotedMessageTap ?? this.onQuotedMessageTap, onQuotedMessageTap: onQuotedMessageTap ?? this.onQuotedMessageTap,
onMessageTap: onMessageTap ?? this.onMessageTap, onMessageTap: onMessageTap ?? this.onMessageTap,
onReactionsTap: onReactionsTap ?? this.onReactionsTap, onReactionsTap: onReactionsTap ?? this.onReactionsTap,
onReactionsHover: onReactionsHover ?? this.onReactionsHover,
customActions: customActions ?? this.customActions, customActions: customActions ?? this.customActions,
onAttachmentTap: onAttachmentTap ?? this.onAttachmentTap, onAttachmentTap: onAttachmentTap ?? this.onAttachmentTap,
userAvatarBuilder: userAvatarBuilder ?? this.userAvatarBuilder, userAvatarBuilder: userAvatarBuilder ?? this.userAvatarBuilder,
@@ -978,7 +991,6 @@ class _StreamMessageWidgetState extends State<StreamMessageWidget>
reverse: widget.reverse, reverse: widget.reverse,
message: widget.message, message: widget.message,
hasNonUrlAttachments: hasNonUrlAttachments, hasNonUrlAttachments: hasNonUrlAttachments,
shouldShowReactions: shouldShowReactions,
hasQuotedMessage: hasQuotedMessage, hasQuotedMessage: hasQuotedMessage,
textPadding: widget.textPadding, textPadding: widget.textPadding,
attachmentBuilders: widget.attachmentBuilders, attachmentBuilders: widget.attachmentBuilders,
@@ -997,6 +1009,7 @@ class _StreamMessageWidgetState extends State<StreamMessageWidget>
? widget.onReactionsTap!(widget.message) ? widget.onReactionsTap!(widget.message)
: _showMessageReactionsModal(context); : _showMessageReactionsModal(context);
}, },
onReactionsHover: widget.onReactionsHover,
showUserAvatar: widget.showUserAvatar, showUserAvatar: widget.showUserAvatar,
streamChat: _streamChat, streamChat: _streamChat,
translateUserAvatar: widget.translateUserAvatar, translateUserAvatar: widget.translateUserAvatar,
@@ -1258,8 +1271,9 @@ class _StreamMessageWidgetState extends State<StreamMessageWidget>
translateUserAvatar: false, translateUserAvatar: false,
showSendingIndicator: false, showSendingIndicator: false,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
// Show both the tail and indicator if the indicator is shown. // Show both the tail if the picker is shown.
showReactionPickerTail: widget.showReactionPickerIndicator, showReactionPicker: widget.showReactionPicker,
showReactionPickerTail: widget.showReactionPicker,
showPinHighlight: false, showPinHighlight: false,
showUserAvatar: widget.message.user!.id == showUserAvatar: widget.message.user!.id ==
channel.client.state.currentUser!.id channel.client.state.currentUser!.id
@@ -1281,7 +1295,6 @@ class _StreamMessageWidgetState extends State<StreamMessageWidget>
showResendMessage: shouldShowResendAction, showResendMessage: shouldShowResendAction,
showCopyMessage: shouldShowCopyAction, showCopyMessage: shouldShowCopyAction,
showEditMessage: shouldShowEditAction, showEditMessage: shouldShowEditAction,
showReactionPicker: widget.showReactionPickerIndicator,
showReplyMessage: shouldShowReplyAction, showReplyMessage: shouldShowReplyAction,
showThreadReplyMessage: shouldShowThreadReplyAction, showThreadReplyMessage: shouldShowThreadReplyAction,
showFlagButton: widget.showFlagButton, showFlagButton: widget.showFlagButton,
@@ -36,8 +36,8 @@ class MessageWidgetContent extends StatelessWidget {
required this.avatarWidth, required this.avatarWidth,
required this.showReactions, required this.showReactions,
required this.onReactionsTap, required this.onReactionsTap,
required this.onReactionsHover,
required this.messageTheme, required this.messageTheme,
required this.shouldShowReactions,
required this.streamChatTheme, required this.streamChatTheme,
required this.isFailedState, required this.isFailedState,
required this.hasQuotedMessage, required this.hasQuotedMessage,
@@ -114,17 +114,15 @@ class MessageWidgetContent extends StatelessWidget {
/// {@macro showReactions} /// {@macro showReactions}
final bool showReactions; final bool showReactions;
/// Callback called when the reactions icon is tapped. /// {@macro onReactionsTap}
///
/// Do not confuse this with the tap action on the reactions picker.
final VoidCallback onReactionsTap; final VoidCallback onReactionsTap;
/// {@macro onReactionsHover}
final OnReactionsHover? onReactionsHover;
/// {@macro messageTheme} /// {@macro messageTheme}
final StreamMessageThemeData messageTheme; final StreamMessageThemeData messageTheme;
/// {@macro shouldShowReactions}
final bool shouldShowReactions;
/// {@macro onUserAvatarTap} /// {@macro onUserAvatarTap}
final void Function(User)? onUserAvatarTap; final void Function(User)? onUserAvatarTap;
@@ -295,7 +293,6 @@ class MessageWidgetContent extends StatelessWidget {
messageTheme: messageTheme, messageTheme: messageTheme,
ownId: streamChat.currentUser!.id, ownId: streamChat.currentUser!.id,
reverse: reverse, reverse: reverse,
shouldShowReactions: shouldShowReactions,
onTap: onReactionsTap, onTap: onReactionsTap,
) )
: null, : null,
@@ -314,25 +311,15 @@ class MessageWidgetContent extends StatelessWidget {
children: [ children: [
Padding( Padding(
padding: showReactions padding: showReactions
? EdgeInsets.only( ? const EdgeInsets.only(top: 18)
top: message.reactionCounts
?.isNotEmpty ==
true
? 18
: 0,
)
: EdgeInsets.zero, : EdgeInsets.zero,
child: (message.isDeleted && !isFailedState) child: (message.isDeleted && !isFailedState)
? Container( ? Container(
// ignore: lines_longer_than_80_chars
margin: EdgeInsets.symmetric( margin: EdgeInsets.symmetric(
horizontal: horizontal: showUserAvatar ==
// ignore: lines_longer_than_80_chars DisplayWidget.gone
showUserAvatar == ? 0
// ignore: lines_longer_than_80_chars : 4.0,
DisplayWidget.gone
? 0
: 4.0,
), ),
child: StreamDeletedMessage( child: StreamDeletedMessage(
borderRadiusGeometry: borderRadiusGeometry:
@@ -405,7 +392,7 @@ class MessageWidgetContent extends StatelessWidget {
SizedBox(width: avatarWidth + 4), SizedBox(width: avatarWidth + 4),
], ],
), ),
if (isDesktopDeviceOrWeb && shouldShowReactions) ...[ if (isDesktopDeviceOrWeb && showReactions) ...[
Padding( Padding(
padding: showUserAvatar != DisplayWidget.gone padding: showUserAvatar != DisplayWidget.gone
? EdgeInsets.only( ? EdgeInsets.only(
@@ -416,7 +403,7 @@ class MessageWidgetContent extends StatelessWidget {
child: DesktopReactionsBuilder( child: DesktopReactionsBuilder(
message: message, message: message,
messageTheme: messageTheme, messageTheme: messageTheme,
shouldShowReactions: shouldShowReactions, onHover: onReactionsHover,
borderSide: borderSide, borderSide: borderSide,
reverse: reverse, reverse: reverse,
), ),
@@ -1,3 +1,5 @@
// ignore_for_file: cascade_invocations
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -5,8 +7,6 @@ import 'package:flutter_portal/flutter_portal.dart';
import 'package:stream_chat_flutter/src/message_widget/reactions/reactions_card.dart'; import 'package:stream_chat_flutter/src/message_widget/reactions/reactions_card.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart';
// ignore_for_file: cascade_invocations
/// {@template desktopReactionsBuilder} /// {@template desktopReactionsBuilder}
/// Builds a list of reactions to a message on desktop & web. /// Builds a list of reactions to a message on desktop & web.
/// ///
@@ -16,16 +16,13 @@ class DesktopReactionsBuilder extends StatefulWidget {
/// {@macro desktopReactionsBuilder} /// {@macro desktopReactionsBuilder}
const DesktopReactionsBuilder({ const DesktopReactionsBuilder({
super.key, super.key,
required this.shouldShowReactions,
required this.message, required this.message,
required this.messageTheme, required this.messageTheme,
this.onHover,
this.borderSide, this.borderSide,
required this.reverse, required this.reverse,
}); });
/// Whether reactions should be shown.
final bool shouldShowReactions;
/// The message to show reactions for. /// The message to show reactions for.
final Message message; final Message message;
@@ -35,6 +32,9 @@ class DesktopReactionsBuilder extends StatefulWidget {
/// reactions matches the design spec for messages. /// reactions matches the design spec for messages.
final StreamMessageThemeData messageTheme; final StreamMessageThemeData messageTheme;
/// Callback to run when the mouse enters or exits the reactions.
final OnReactionsHover? onHover;
/// {@macro borderSide} /// {@macro borderSide}
final BorderSide? borderSide; final BorderSide? borderSide;
@@ -48,12 +48,6 @@ class DesktopReactionsBuilder extends StatefulWidget {
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
properties.add(
DiagnosticsProperty<bool>(
'shouldShowReactions',
shouldShowReactions,
),
);
properties.add( properties.add(
DiagnosticsProperty<Message>('message', message), DiagnosticsProperty<Message>('message', message),
); );
@@ -81,18 +75,15 @@ class _DesktopReactionsBuilderState extends State<DesktopReactionsBuilder> {
final streamChatTheme = StreamChatTheme.of(context); final streamChatTheme = StreamChatTheme.of(context);
final reactionsMap = <String, Reaction>{}; final reactionsMap = <String, Reaction>{};
var reactionsList = <Reaction>[]; widget.message.latestReactions?.forEach((element) {
if (widget.shouldShowReactions) { if (!reactionsMap.containsKey(element.type) ||
widget.message.latestReactions?.forEach((element) { element.user!.id == currentUser.id) {
if (!reactionsMap.containsKey(element.type) || reactionsMap[element.type] = element;
element.user!.id == currentUser.id) { }
reactionsMap[element.type] = element; });
}
});
reactionsList = reactionsMap.values.toList() final reactionsList = reactionsMap.values.toList()
..sort((a, b) => a.user!.id == currentUser.id ? 1 : -1); ..sort((a, b) => a.user!.id == currentUser.id ? 1 : -1);
}
return PortalTarget( return PortalTarget(
visible: _showReactionsPopup, visible: _showReactionsPopup,
@@ -100,17 +91,11 @@ class _DesktopReactionsBuilderState extends State<DesktopReactionsBuilder> {
anchor: Aligned( anchor: Aligned(
target: widget.reverse ? Alignment.topRight : Alignment.topLeft, target: widget.reverse ? Alignment.topRight : Alignment.topLeft,
follower: widget.reverse ? Alignment.bottomRight : Alignment.bottomLeft, follower: widget.reverse ? Alignment.bottomRight : Alignment.bottomLeft,
shiftToWithinBound: const AxisFlag( shiftToWithinBound: const AxisFlag(y: true),
y: true,
),
), ),
portalFollower: MouseRegion( portalFollower: MouseRegion(
onEnter: (event) async { onEnter: (_) => _onReactionsHover(true),
setState(() => _showReactionsPopup = !_showReactionsPopup); onExit: (_) => _onReactionsHover(false),
},
onExit: (event) {
setState(() => _showReactionsPopup = !_showReactionsPopup);
},
child: ConstrainedBox( child: ConstrainedBox(
constraints: const BoxConstraints( constraints: const BoxConstraints(
maxWidth: 336, maxWidth: 336,
@@ -125,12 +110,8 @@ class _DesktopReactionsBuilderState extends State<DesktopReactionsBuilder> {
), ),
child: MouseRegion( child: MouseRegion(
cursor: SystemMouseCursors.click, cursor: SystemMouseCursors.click,
onEnter: (event) async { onEnter: (_) => _onReactionsHover(true),
setState(() => _showReactionsPopup = !_showReactionsPopup); onExit: (_) => _onReactionsHover(false),
},
onExit: (event) {
setState(() => _showReactionsPopup = !_showReactionsPopup);
},
child: Padding( child: Padding(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
vertical: 2, vertical: 2,
@@ -161,6 +142,14 @@ class _DesktopReactionsBuilderState extends State<DesktopReactionsBuilder> {
), ),
); );
} }
void _onReactionsHover(bool isHovering) {
if (widget.onHover != null) {
return widget.onHover!(isHovering);
}
setState(() => _showReactionsPopup = isHovering);
}
} }
class _BottomReaction extends StatelessWidget { class _BottomReaction extends StatelessWidget {
@@ -13,7 +13,6 @@ class ReactionIndicator extends StatelessWidget {
super.key, super.key,
required this.ownId, required this.ownId,
required this.message, required this.message,
required this.shouldShowReactions,
required this.onTap, required this.onTap,
required this.reverse, required this.reverse,
required this.messageTheme, required this.messageTheme,
@@ -25,9 +24,6 @@ class ReactionIndicator extends StatelessWidget {
/// {@macro message} /// {@macro message}
final Message message; final Message message;
/// {@macro shouldShowReactions}
final bool shouldShowReactions;
/// The callback to perform when the widget is tapped or clicked. /// The callback to perform when the widget is tapped or clicked.
final VoidCallback onTap; final VoidCallback onTap;
@@ -50,34 +46,27 @@ class ReactionIndicator extends StatelessWidget {
..sort((a, b) => a.user!.id == ownId ? 1 : -1); ..sort((a, b) => a.user!.id == ownId ? 1 : -1);
return Transform( return Transform(
transform: Matrix4.translationValues( transform: Matrix4.translationValues(reverse ? 12 : -12, 0, 0),
reverse ? 12 : -12,
0,
0,
),
child: ConstrainedBox( child: ConstrainedBox(
constraints: const BoxConstraints( constraints: const BoxConstraints(
maxWidth: 22 * 6.0, maxWidth: 22 * 6.0,
), ),
child: AnimatedSwitcher( child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 300),
child: shouldShowReactions child: GestureDetector(
? GestureDetector( onTap: onTap,
onTap: onTap, child: StreamReactionBubble(
child: StreamReactionBubble( key: ValueKey('${message.id}.reactions'),
key: ValueKey('${message.id}.reactions'), reverse: reverse,
reverse: reverse, flipTail: reverse,
flipTail: reverse, backgroundColor:
backgroundColor: messageTheme.reactionsBackgroundColor ?? messageTheme.reactionsBackgroundColor ?? Colors.transparent,
Colors.transparent, borderColor:
borderColor: messageTheme.reactionsBorderColor ?? Colors.transparent,
messageTheme.reactionsBorderColor ?? Colors.transparent, maskColor: messageTheme.reactionsMaskColor ?? Colors.transparent,
maskColor: reactions: reactionsList,
messageTheme.reactionsMaskColor ?? Colors.transparent, ),
reactions: reactionsList, ),
),
)
: const SizedBox(),
), ),
), ),
); );
@@ -235,6 +235,12 @@ typedef OnMessageTap = void Function(Message);
/// {@endtemplate} /// {@endtemplate}
typedef OnReactionsTap = void Function(Message); typedef OnReactionsTap = void Function(Message);
/// {@template onReactionsHover}
/// The action to perform when a message's reactions are hovered.
/// {@endtemplate}
// ignore: avoid_positional_boolean_parameters
typedef OnReactionsHover = void Function(bool isHovering);
/// {@template messageSearchItemTapCallback} /// {@template messageSearchItemTapCallback}
/// The action to perform when tapping or clicking on a user in a /// The action to perform when tapping or clicking on a user in a
// ignore: deprecated_member_use_from_same_package // ignore: deprecated_member_use_from_same_package
+2 -2
View File
@@ -1,7 +1,7 @@
name: stream_chat_flutter name: stream_chat_flutter
homepage: https://github.com/GetStream/stream-chat-flutter homepage: https://github.com/GetStream/stream-chat-flutter
description: Stream Chat official Flutter SDK. Build your own chat experience using Dart and Flutter. description: Stream Chat official Flutter SDK. Build your own chat experience using Dart and Flutter.
version: 6.9.0 version: 6.10.0
repository: https://github.com/GetStream/stream-chat-flutter repository: https://github.com/GetStream/stream-chat-flutter
issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
@@ -38,7 +38,7 @@ dependencies:
rxdart: ^0.27.7 rxdart: ^0.27.7
share_plus: ^7.1.0 share_plus: ^7.1.0
shimmer: ^3.0.0 shimmer: ^3.0.0
stream_chat_flutter_core: ^6.8.0 stream_chat_flutter_core: ^6.9.0
synchronized: ^3.1.0 synchronized: ^3.1.0
thumblr: ^0.0.4 thumblr: ^0.0.4
url_launcher: ^6.1.12 url_launcher: ^6.1.12
+11 -3
View File
@@ -1,3 +1,8 @@
## 6.9.0
- Added support for `StreamChannel.loadingBuilder` and `StreamChannel.errorBuilder` to customize
loading and error states.
## 6.8.0 ## 6.8.0
- Updated minimum supported `SDK` version to Flutter 3.10/Dart 3.0 - Updated minimum supported `SDK` version to Flutter 3.10/Dart 3.0
@@ -35,9 +40,11 @@
- Updated `dart` sdk environment range to support `3.0.0`. - Updated `dart` sdk environment range to support `3.0.0`.
- Updated `stream_chat` dependency to [`6.1.0`](https://pub.dev/packages/stream_chat/changelog). - Updated `stream_chat` dependency to [`6.1.0`](https://pub.dev/packages/stream_chat/changelog).
- [[#1356]](https://github.com/GetStream/stream-chat-flutter/issues/1356) Channel doesn't auto display again after being - [[#1356]](https://github.com/GetStream/stream-chat-flutter/issues/1356) Channel doesn't auto
display again after being
hidden. hidden.
- [[#1540]](https://github.com/GetStream/stream-chat-flutter/issues/1540) Use `CircularProgressIndicator.adaptive` - [[#1540]](https://github.com/GetStream/stream-chat-flutter/issues/1540)
Use `CircularProgressIndicator.adaptive`
instead of material indicator. instead of material indicator.
## 6.0.0 ## 6.0.0
@@ -56,7 +63,8 @@
## 5.1.0 ## 5.1.0
- Deprecated the `sort` parameter in the `StreamChannelListController` in favor of `channelStateSort`. - Deprecated the `sort` parameter in the `StreamChannelListController` in favor
of `channelStateSort`.
## 5.0.0 ## 5.0.0
@@ -15,6 +15,15 @@ enum QueryDirection {
bottom, bottom,
} }
/// Signature used by [StreamChannel.errorBuilder] to create a replacement
/// widget for an error that occurs while asynchronously building the channel.
// TODO: Remove once ErrorBuilder supports passing stacktrace.
typedef ErrorWidgetBuilder = Widget Function(
BuildContext context,
Object error,
StackTrace? stackTrace,
);
/// Widget used to provide information about the channel to the widget tree /// Widget used to provide information about the channel to the widget tree
/// ///
/// Use [StreamChannel.of] to get the current [StreamChannelState] instance. /// Use [StreamChannel.of] to get the current [StreamChannelState] instance.
@@ -27,6 +36,8 @@ class StreamChannel extends StatefulWidget {
required this.channel, required this.channel,
this.showLoading = true, this.showLoading = true,
this.initialMessageId, this.initialMessageId,
this.errorBuilder = _defaultErrorBuilder,
this.loadingBuilder = _defaultLoadingBuilder,
}); });
/// The child of the widget /// The child of the widget
@@ -41,6 +52,31 @@ class StreamChannel extends StatefulWidget {
/// If passed the channel will load from this particular message. /// If passed the channel will load from this particular message.
final String? initialMessageId; final String? initialMessageId;
/// Widget builder used in case the channel is initialising.
final WidgetBuilder loadingBuilder;
/// Widget builder used in case an error occurs while building the channel.
final ErrorWidgetBuilder errorBuilder;
static Widget _defaultLoadingBuilder(BuildContext context) {
return const Center(child: CircularProgressIndicator.adaptive());
}
static Widget _defaultErrorBuilder(
BuildContext context,
Object error,
StackTrace? stackTrace,
) {
if (error is DioException) {
if (error.type == DioExceptionType.badResponse) {
return Center(child: Text(error.message ?? 'Bad response'));
}
return const Center(child: Text('Check your connection and retry'));
}
return Center(child: Text(error.toString()));
}
/// Use this method to get the current [StreamChannelState] instance /// Use this method to get the current [StreamChannelState] instance
static StreamChannelState of(BuildContext context) { static StreamChannelState of(BuildContext context) {
StreamChannelState? streamChannelState; StreamChannelState? streamChannelState;
@@ -430,22 +466,14 @@ class StreamChannelState extends State<StreamChannel> {
], ],
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasError) { if (snapshot.hasError) {
final error = snapshot.error; final error = snapshot.error!;
if (error is DioException) { final stackTrace = snapshot.stackTrace;
if (error.type == DioExceptionType.badResponse) { return widget.errorBuilder(context, error, stackTrace);
return Center(child: Text(error.message ?? 'Bad response'));
}
return const Center(child: Text('Check your connection and retry'));
}
return Center(child: Text(error.toString()));
} }
final dataLoaded = snapshot.data?.every((it) => it) == true; final dataLoaded = snapshot.data?.every((it) => it) == true;
if (widget.showLoading && !dataLoaded) { if (widget.showLoading && !dataLoaded) {
return const Center( return widget.loadingBuilder(context);
child: CircularProgressIndicator.adaptive(),
);
} }
return widget.child; return widget.child;
}, },
@@ -4,6 +4,7 @@ import 'package:stream_chat/stream_chat.dart';
/// A signature for a callback which exposes an error and returns a function. /// A signature for a callback which exposes an error and returns a function.
/// This Callback can be used in cases where an API failure occurs and the /// This Callback can be used in cases where an API failure occurs and the
/// widget is unable to render data. /// widget is unable to render data.
// TODO: Add stacktrace as a parameter in v7.0.0
typedef ErrorBuilder = Widget Function(BuildContext context, Object error); typedef ErrorBuilder = Widget Function(BuildContext context, Object error);
/// A Signature for a handler function which will expose a [event]. /// A Signature for a handler function which will expose a [event].
@@ -1,7 +1,7 @@
name: stream_chat_flutter_core name: stream_chat_flutter_core
homepage: https://github.com/GetStream/stream-chat-flutter homepage: https://github.com/GetStream/stream-chat-flutter
description: Stream Chat official Flutter SDK Core. Build your own chat experience using Dart and Flutter. description: Stream Chat official Flutter SDK Core. Build your own chat experience using Dart and Flutter.
version: 6.8.0 version: 6.9.0
repository: https://github.com/GetStream/stream-chat-flutter repository: https://github.com/GetStream/stream-chat-flutter
issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
@@ -17,7 +17,7 @@ dependencies:
freezed_annotation: ^2.4.1 freezed_annotation: ^2.4.1
meta: ^1.9.1 meta: ^1.9.1
rxdart: ^0.27.7 rxdart: ^0.27.7
stream_chat: ^6.8.0 stream_chat: ^6.9.0
dev_dependencies: dev_dependencies:
build_runner: ^2.4.6 build_runner: ^2.4.6
@@ -1,3 +1,7 @@
## 5.10.0
* Updated `stream_chat_flutter` dependency to [`6.10.0`](https://pub.dev/packages/stream_chat_flutter/changelog).
## 5.9.0 ## 5.9.0
* Updated minimum supported `SDK` version to Flutter 3.10/Dart 3.0 * Updated minimum supported `SDK` version to Flutter 3.10/Dart 3.0
@@ -1,6 +1,6 @@
name: stream_chat_localizations name: stream_chat_localizations
description: The Official localizations for Stream Chat Flutter, a service for building chat applications description: The Official localizations for Stream Chat Flutter, a service for building chat applications
version: 5.9.0 version: 5.10.0
homepage: https://github.com/GetStream/stream-chat-flutter homepage: https://github.com/GetStream/stream-chat-flutter
repository: https://github.com/GetStream/stream-chat-flutter repository: https://github.com/GetStream/stream-chat-flutter
issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
@@ -14,7 +14,7 @@ dependencies:
sdk: flutter sdk: flutter
flutter_localizations: flutter_localizations:
sdk: flutter sdk: flutter
stream_chat_flutter: ^6.9.0 stream_chat_flutter: ^6.10.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
@@ -1,3 +1,7 @@
## 6.9.0
- Updated `stream_chat` dependency to [`6.9.0`](https://pub.dev/packages/stream_chat/changelog).
## 6.8.0 ## 6.8.0
- Updated minimum supported `SDK` version to Flutter 3.10/Dart 3.0 - Updated minimum supported `SDK` version to Flutter 3.10/Dart 3.0
@@ -1,7 +1,7 @@
name: stream_chat_persistence name: stream_chat_persistence
homepage: https://github.com/GetStream/stream-chat-flutter homepage: https://github.com/GetStream/stream-chat-flutter
description: Official Stream Chat Persistence library. Build your own chat experience using Dart and Flutter. description: Official Stream Chat Persistence library. Build your own chat experience using Dart and Flutter.
version: 6.8.0 version: 6.9.0
repository: https://github.com/GetStream/stream-chat-flutter repository: https://github.com/GetStream/stream-chat-flutter
issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
@@ -18,7 +18,7 @@ dependencies:
path: ^1.8.3 path: ^1.8.3
path_provider: ^2.1.0 path_provider: ^2.1.0
sqlite3_flutter_libs: ^0.5.15 sqlite3_flutter_libs: ^0.5.15
stream_chat: ^6.8.0 stream_chat: ^6.9.0
dev_dependencies: dev_dependencies:
build_runner: ^2.4.6 build_runner: ^2.4.6