Merge pull request #1524 from GetStream/fix/own-message-border-color

This commit is contained in:
Sahil Kumar
2023-05-09 13:08:12 +05:30
committed by GitHub
23 changed files with 250 additions and 311 deletions
@@ -997,26 +997,24 @@ class Channel {
) async { ) async {
final type = reaction.type; final type = reaction.type;
final reactionCounts = {...message.reactionCounts ?? <String, int>{}}; final reactionCounts = {...?message.reactionCounts};
if (reactionCounts.containsKey(type)) { if (reactionCounts.containsKey(type)) {
reactionCounts.update(type, (value) => value - 1); reactionCounts.update(type, (value) => value - 1);
} }
final reactionScores = {...message.reactionScores ?? <String, int>{}}; final reactionScores = {...?message.reactionScores};
if (reactionScores.containsKey(type)) { if (reactionScores.containsKey(type)) {
reactionScores.update(type, (value) => value - 1); reactionScores.update(type, (value) => value - 1);
} }
final latestReactions = [...message.latestReactions ?? <Reaction>[]] final latestReactions = [...?message.latestReactions]..removeWhere((r) =>
..removeWhere((r) => r.userId == reaction.userId &&
r.userId == reaction.userId && r.type == reaction.type &&
r.type == reaction.type && r.messageId == reaction.messageId);
r.messageId == reaction.messageId);
final ownReactions = message.ownReactions final ownReactions = [...?message.ownReactions]..removeWhere((r) =>
?..removeWhere((r) => r.userId == reaction.userId &&
r.userId == reaction.userId && r.type == reaction.type &&
r.type == reaction.type && r.messageId == reaction.messageId);
r.messageId == reaction.messageId);
final newMessage = message.copyWith( final newMessage = message.copyWith(
reactionCounts: reactionCounts..removeWhere((_, value) => value == 0), reactionCounts: reactionCounts..removeWhere((_, value) => value == 0),
@@ -11,6 +11,8 @@
works only for otherUser. works only for otherUser.
- [[#1490]](https://github.com/GetStream/stream-chat-flutter/issues/1490) Fixed `editMessageInputBuilder` property not - [[#1490]](https://github.com/GetStream/stream-chat-flutter/issues/1490) Fixed `editMessageInputBuilder` property not
used in message edit widget. used in message edit widget.
- [[#1523]](https://github.com/GetStream/stream-chat-flutter/issues/1523) Fixed `StreamMessageThemeData` not being
applied correctly.
✅ Added ✅ Added
@@ -893,6 +893,11 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
final currentUserMember = final currentUserMember =
members.firstWhereOrNull((e) => e.user!.id == currentUser!.id); members.firstWhereOrNull((e) => e.user!.id == currentUser!.id);
final hasUrlAttachment =
message.attachments.any((it) => it.ogScrapeUrl != null);
final borderSide = isOnlyEmoji || hasUrlAttachment ? BorderSide.none : null;
final defaultMessageWidget = StreamMessageWidget( final defaultMessageWidget = StreamMessageWidget(
showReplyMessage: false, showReplyMessage: false,
showResendMessage: false, showResendMessage: false,
@@ -917,7 +922,7 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
vertical: 8, vertical: 8,
horizontal: isOnlyEmoji ? 0 : 16.0, horizontal: isOnlyEmoji ? 0 : 16.0,
), ),
borderSide: isMyMessage || isOnlyEmoji ? BorderSide.none : null, borderSide: borderSide,
showUserAvatar: isMyMessage ? DisplayWidget.gone : DisplayWidget.show, showUserAvatar: isMyMessage ? DisplayWidget.gone : DisplayWidget.show,
messageTheme: isMyMessage messageTheme: isMyMessage
? _streamTheme.ownMessageTheme ? _streamTheme.ownMessageTheme
@@ -1096,10 +1101,7 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
final hasUrlAttachment = final hasUrlAttachment =
message.attachments.any((it) => it.ogScrapeUrl != null); message.attachments.any((it) => it.ogScrapeUrl != null);
final borderSide = final borderSide = isOnlyEmoji || hasUrlAttachment ? BorderSide.none : null;
isOnlyEmoji || hasUrlAttachment || (isMyMessage && !hasFileAttachment)
? BorderSide.none
: null;
final currentUser = StreamChat.of(context).currentUser; final currentUser = StreamChat.of(context).currentUser;
final members = StreamChannel.of(context).channel.state?.members ?? []; final members = StreamChannel.of(context).channel.state?.members ?? [];
@@ -32,7 +32,6 @@ class StreamDeletedMessage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final chatThemeData = StreamChatTheme.of(context);
return Material( return Material(
color: messageTheme.messageBackgroundColor, color: messageTheme.messageBackgroundColor,
shape: shape ?? shape: shape ??
@@ -40,9 +39,7 @@ class StreamDeletedMessage extends StatelessWidget {
borderRadius: borderRadiusGeometry ?? BorderRadius.zero, borderRadius: borderRadiusGeometry ?? BorderRadius.zero,
side: borderSide ?? side: borderSide ??
BorderSide( BorderSide(
color: Theme.of(context).brightness == Brightness.dark color: messageTheme.messageBorderColor ?? Colors.transparent,
? chatThemeData.colorTheme.barsBg.withAlpha(24)
: chatThemeData.colorTheme.textHighEmphasis.withAlpha(24),
), ),
), ),
child: Padding( child: Padding(
@@ -139,7 +139,8 @@ class _MessageCardState extends State<MessageCard> {
RoundedRectangleBorder( RoundedRectangleBorder(
side: widget.borderSide ?? side: widget.borderSide ??
BorderSide( BorderSide(
color: widget.messageTheme.messageBorderColor ?? Colors.grey, color: widget.messageTheme.messageBorderColor ??
Colors.transparent,
), ),
borderRadius: widget.borderRadiusGeometry ?? BorderRadius.zero, borderRadius: widget.borderRadiusGeometry ?? BorderRadius.zero,
), ),
@@ -2,6 +2,7 @@ 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';
import 'package:flutter_portal/flutter_portal.dart'; import 'package:flutter_portal/flutter_portal.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 // ignore_for_file: cascade_invocations
@@ -75,6 +76,7 @@ class _DesktopReactionsBuilderState extends State<DesktopReactionsBuilder> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final streamChat = StreamChat.of(context); final streamChat = StreamChat.of(context);
final currentUser = streamChat.currentUser!;
final reactionIcons = StreamChatConfiguration.of(context).reactionIcons; final reactionIcons = StreamChatConfiguration.of(context).reactionIcons;
final streamChatTheme = StreamChatTheme.of(context); final streamChatTheme = StreamChatTheme.of(context);
@@ -83,13 +85,13 @@ class _DesktopReactionsBuilderState extends State<DesktopReactionsBuilder> {
if (widget.shouldShowReactions) { if (widget.shouldShowReactions) {
widget.message.latestReactions?.forEach((element) { widget.message.latestReactions?.forEach((element) {
if (!reactionsMap.containsKey(element.type) || if (!reactionsMap.containsKey(element.type) ||
element.user!.id == streamChat.currentUser?.id) { element.user!.id == currentUser.id) {
reactionsMap[element.type] = element; reactionsMap[element.type] = element;
} }
}); });
reactionsList = reactionsMap.values.toList() reactionsList = reactionsMap.values.toList()
..sort((a, b) => a.user!.id == streamChat.currentUser?.id ? 1 : -1); ..sort((a, b) => a.user!.id == currentUser.id ? 1 : -1);
} }
return PortalTarget( return PortalTarget(
@@ -114,44 +116,10 @@ class _DesktopReactionsBuilderState extends State<DesktopReactionsBuilder> {
maxWidth: 336, maxWidth: 336,
maxHeight: 342, maxHeight: 342,
), ),
child: Card( child: ReactionsCard(
color: streamChatTheme.colorTheme.barsBg, currentUser: currentUser,
shape: RoundedRectangleBorder( message: widget.message,
borderRadius: BorderRadius.circular(16), messageTheme: widget.messageTheme,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Text(
'''${widget.message.latestReactions!.length} ${context.translations.messageReactionsLabel}''',
style: streamChatTheme.textTheme.headlineBold,
),
),
Flexible(
child: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Wrap(
spacing: 16,
runSpacing: 16,
children: [
...widget.message.latestReactions!.map((reaction) {
final reactionIcon = reactionIcons.firstWhereOrNull(
(r) => r.type == reaction.type,
);
return _StackedReaction(
reaction: reaction,
streamChatTheme: streamChatTheme,
reactionIcon: reactionIcon,
);
}).toList(),
],
),
),
),
],
),
), ),
), ),
), ),
@@ -163,23 +131,32 @@ class _DesktopReactionsBuilderState extends State<DesktopReactionsBuilder> {
onExit: (event) { onExit: (event) {
setState(() => _showReactionsPopup = !_showReactionsPopup); setState(() => _showReactionsPopup = !_showReactionsPopup);
}, },
child: Wrap( child: Padding(
children: [ padding: EdgeInsets.symmetric(
...reactionsList.map((reaction) { vertical: 2,
final reactionIcon = reactionIcons.firstWhereOrNull( horizontal: widget.reverse ? 0 : 4,
(r) => r.type == reaction.type, ),
); child: Wrap(
spacing: 4,
runSpacing: 4,
children: [
...reactionsList.map((reaction) {
final reactionIcon = reactionIcons.firstWhereOrNull(
(r) => r.type == reaction.type,
);
return _BottomReaction( return _BottomReaction(
reaction: reaction, currentUser: currentUser,
message: widget.message, reaction: reaction,
borderSide: widget.borderSide, message: widget.message,
messageTheme: widget.messageTheme, borderSide: widget.borderSide,
reactionIcon: reactionIcon, messageTheme: widget.messageTheme,
streamChatTheme: streamChatTheme, reactionIcon: reactionIcon,
); streamChatTheme: streamChatTheme,
}).toList(), );
], }).toList(),
],
),
), ),
), ),
); );
@@ -188,6 +165,7 @@ class _DesktopReactionsBuilderState extends State<DesktopReactionsBuilder> {
class _BottomReaction extends StatelessWidget { class _BottomReaction extends StatelessWidget {
const _BottomReaction({ const _BottomReaction({
required this.currentUser,
required this.reaction, required this.reaction,
required this.message, required this.message,
required this.borderSide, required this.borderSide,
@@ -196,6 +174,7 @@ class _BottomReaction extends StatelessWidget {
required this.streamChatTheme, required this.streamChatTheme,
}); });
final User currentUser;
final Reaction reaction; final Reaction reaction;
final Message message; final Message message;
final BorderSide? borderSide; final BorderSide? borderSide;
@@ -205,7 +184,10 @@ class _BottomReaction extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final userId = StreamChat.of(context).currentUser?.id; final userId = currentUser.id;
final backgroundColor = messageTheme?.reactionsBackgroundColor;
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () { onTap: () {
@@ -225,37 +207,38 @@ class _BottomReaction extends StatelessWidget {
} }
}, },
child: Card( child: Card(
shape: StadiumBorder( margin: EdgeInsets.zero,
// Setting elevation as null when background color is transparent.
// This is done to avoid shadow when background color is transparent.
elevation: backgroundColor == Colors.transparent ? 0 : null,
shape: RoundedRectangleBorder(
side: borderSide ?? side: borderSide ??
BorderSide( BorderSide(
color: messageTheme?.messageBorderColor ?? Colors.grey, color: messageTheme?.reactionsBorderColor ?? Colors.transparent,
), ),
borderRadius: BorderRadius.circular(10),
), ),
color: messageTheme?.messageBackgroundColor, color: backgroundColor,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
horizontal: 6,
vertical: 2,
),
child: Row( child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
ConstrainedBox( ConstrainedBox(
constraints: BoxConstraints.tight( constraints: BoxConstraints.tight(
const Size.square(16), const Size.square(14),
), ),
child: reactionIcon?.builder( child: reactionIcon?.builder(
context, context,
reaction.user?.id == userId, reaction.user?.id == userId,
16, 14,
) ?? ) ??
Icon( Icon(
Icons.help_outline_rounded, Icons.help_outline_rounded,
size: 16, size: 14,
color: reaction.user?.id == userId color: reaction.user?.id == userId
? streamChatTheme.colorTheme.accentPrimary ? streamChatTheme.colorTheme.accentPrimary
: streamChatTheme.colorTheme.textHighEmphasis : streamChatTheme.colorTheme.textLowEmphasis,
.withOpacity(0.5),
), ),
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
@@ -280,87 +263,3 @@ class _BottomReaction extends StatelessWidget {
properties.add(DiagnosticsProperty<Message>('message', message)); properties.add(DiagnosticsProperty<Message>('message', message));
} }
} }
class _StackedReaction extends StatelessWidget {
const _StackedReaction({
required this.reaction,
required this.streamChatTheme,
required this.reactionIcon,
});
final Reaction reaction;
final StreamChatThemeData streamChatTheme;
final StreamReactionIcon? reactionIcon;
@override
Widget build(BuildContext context) {
final userId = StreamChat.of(context).currentUser?.id;
return SizedBox(
width: 80,
child: Column(
children: [
Stack(
children: [
StreamUserAvatar(
user: reaction.user!,
constraints: const BoxConstraints.tightFor(
height: 64,
width: 64,
),
borderRadius: BorderRadius.circular(32),
),
Positioned(
bottom: 0,
right: 0,
child: DecoratedBox(
decoration: BoxDecoration(
color: streamChatTheme.colorTheme.inputBg,
border: Border.all(
color: streamChatTheme.colorTheme.barsBg,
width: 2,
),
shape: BoxShape.circle,
),
child: Padding(
padding: const EdgeInsets.all(8),
child: reactionIcon?.builder(
context,
reaction.userId == userId,
16,
) ??
Icon(
Icons.help_outline_rounded,
size: 16,
color: reaction.user?.id == userId
? streamChatTheme.colorTheme.accentPrimary
: streamChatTheme.colorTheme.textHighEmphasis
.withOpacity(0.5),
),
),
),
),
],
),
Text(
userId == reaction.user!.name ? 'You' : reaction.user!.name,
textAlign: TextAlign.center,
),
],
),
);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(
DiagnosticsProperty<Reaction>('reaction', reaction),
);
properties.add(
DiagnosticsProperty<StreamReactionIcon?>(
'reactionIcon',
reactionIcon,
),
);
}
}
@@ -1,8 +1,8 @@
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/message_widget/reactions/reaction_bubble.dart';
import 'package:stream_chat_flutter/src/message_widget/reactions/reactions_align.dart'; import 'package:stream_chat_flutter/src/message_widget/reactions/reactions_align.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';
/// {@template streamMessageReactionsModal} /// {@template streamMessageReactionsModal}
@@ -83,9 +83,10 @@ class StreamMessageReactionsModal extends StatelessWidget {
), ),
if (message.latestReactions?.isNotEmpty == true) ...[ if (message.latestReactions?.isNotEmpty == true) ...[
const SizedBox(height: 8), const SizedBox(height: 8),
_buildReactionCard( ReactionsCard(
context, currentUser: user!,
user, message: message,
messageTheme: messageTheme,
), ),
], ],
], ],
@@ -126,109 +127,4 @@ class StreamMessageReactionsModal extends StatelessWidget {
), ),
); );
} }
Widget _buildReactionCard(BuildContext context, User? user) {
final chatThemeData = StreamChatTheme.of(context);
return Card(
color: chatThemeData.colorTheme.barsBg,
clipBehavior: Clip.hardEdge,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
margin: EdgeInsets.zero,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
context.translations.messageReactionsLabel,
style: chatThemeData.textTheme.headlineBold,
),
const SizedBox(height: 16),
Flexible(
child: SingleChildScrollView(
child: Wrap(
spacing: 16,
runSpacing: 16,
children: message.latestReactions!
.map((e) => _buildReaction(
e,
user!,
context,
))
.toList(),
),
),
),
],
),
),
);
}
Widget _buildReaction(
Reaction reaction,
User currentUser,
BuildContext context,
) {
final isCurrentUser = reaction.user?.id == currentUser.id;
final chatThemeData = StreamChatTheme.of(context);
return ConstrainedBox(
constraints: BoxConstraints.loose(
const Size(64, 100),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Stack(
clipBehavior: Clip.none,
children: [
StreamUserAvatar(
onTap: onUserAvatarTap,
user: reaction.user!,
constraints: const BoxConstraints.tightFor(
height: 64,
width: 64,
),
onlineIndicatorConstraints: const BoxConstraints.tightFor(
height: 12,
width: 12,
),
borderRadius: BorderRadius.circular(32),
),
Positioned(
bottom: 6,
left: isCurrentUser ? -3 : null,
right: isCurrentUser ? -3 : null,
child: Align(
alignment:
reverse ? Alignment.centerRight : Alignment.centerLeft,
child: StreamReactionBubble(
reactions: [reaction],
flipTail: !reverse,
borderColor:
messageTheme.reactionsBorderColor ?? Colors.transparent,
backgroundColor: messageTheme.reactionsBackgroundColor ??
Colors.transparent,
maskColor: chatThemeData.colorTheme.barsBg,
tailCirclesSpacing: 1,
highlightOwnReactions: false,
),
),
),
],
),
const SizedBox(height: 8),
Text(
reaction.user!.name.split(' ')[0],
style: chatThemeData.textTheme.footnoteBold,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
],
),
);
}
} }
@@ -124,24 +124,22 @@ class StreamReactionBubble extends StatelessWidget {
final chatThemeData = StreamChatTheme.of(context); final chatThemeData = StreamChatTheme.of(context);
final userId = StreamChat.of(context).currentUser?.id; final userId = StreamChat.of(context).currentUser?.id;
return Padding( return Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(horizontal: 4),
horizontal: 4,
),
child: reactionIcon != null child: reactionIcon != null
? ConstrainedBox( ? ConstrainedBox(
constraints: BoxConstraints.tight(const Size.square(16)), constraints: BoxConstraints.tight(const Size.square(14)),
child: reactionIcon.builder( child: reactionIcon.builder(
context, context,
!highlightOwnReactions || reaction.user?.id == userId, highlightOwnReactions && reaction.user?.id == userId,
16, 16,
), ),
) )
: Icon( : Icon(
Icons.help_outline_rounded, Icons.help_outline_rounded,
size: 16, size: 14,
color: (!highlightOwnReactions || reaction.user?.id == userId) color: (highlightOwnReactions && reaction.user?.id == userId)
? chatThemeData.colorTheme.accentPrimary ? chatThemeData.colorTheme.accentPrimary
: chatThemeData.colorTheme.textHighEmphasis.withOpacity(0.5), : chatThemeData.colorTheme.textLowEmphasis,
), ),
); );
} }
@@ -0,0 +1,142 @@
import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/avatars/user_avatar.dart';
import 'package:stream_chat_flutter/src/message_widget/reactions/reaction_bubble.dart';
import 'package:stream_chat_flutter/src/theme/message_theme.dart';
import 'package:stream_chat_flutter/src/theme/stream_chat_theme.dart';
import 'package:stream_chat_flutter/src/utils/extensions.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
/// {@template reactionsCard}
/// A card that displays the reactions to a message.
///
/// Used in [StreamMessageReactionsModal] and [DesktopReactionsBuilder].
/// {@endtemplate}
class ReactionsCard extends StatelessWidget {
/// {@macro reactionsCard}
const ReactionsCard({
super.key,
required this.currentUser,
required this.message,
required this.messageTheme,
this.onUserAvatarTap,
});
/// Current logged in user.
final User currentUser;
/// Message to display reactions of.
final Message message;
/// [StreamMessageThemeData] to apply to [message].
final StreamMessageThemeData messageTheme;
/// {@macro onUserAvatarTap}
final void Function(User)? onUserAvatarTap;
@override
Widget build(BuildContext context) {
final chatThemeData = StreamChatTheme.of(context);
return Card(
color: chatThemeData.colorTheme.barsBg,
clipBehavior: Clip.hardEdge,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
margin: EdgeInsets.zero,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
context.translations.messageReactionsLabel,
style: chatThemeData.textTheme.headlineBold,
),
const SizedBox(height: 16),
Flexible(
child: SingleChildScrollView(
child: Wrap(
spacing: 16,
runSpacing: 16,
children: message.latestReactions!
.map((e) => _buildReaction(
e,
currentUser,
context,
))
.toList(),
),
),
),
],
),
),
);
}
Widget _buildReaction(
Reaction reaction,
User currentUser,
BuildContext context,
) {
final isCurrentUser = reaction.user?.id == currentUser.id;
final chatThemeData = StreamChatTheme.of(context);
final reverse = !isCurrentUser;
return ConstrainedBox(
constraints: BoxConstraints.loose(
const Size(64, 100),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Stack(
clipBehavior: Clip.none,
children: [
StreamUserAvatar(
onTap: onUserAvatarTap,
user: reaction.user!,
constraints: const BoxConstraints.tightFor(
height: 64,
width: 64,
),
onlineIndicatorConstraints: const BoxConstraints.tightFor(
height: 12,
width: 12,
),
borderRadius: BorderRadius.circular(32),
),
Positioned(
bottom: 6,
left: !reverse ? -3 : null,
right: reverse ? -3 : null,
child: Align(
alignment:
reverse ? Alignment.centerRight : Alignment.centerLeft,
child: StreamReactionBubble(
reactions: [reaction],
reverse: !reverse,
flipTail: !reverse,
borderColor:
messageTheme.reactionsBorderColor ?? Colors.transparent,
backgroundColor: messageTheme.reactionsBackgroundColor ??
Colors.transparent,
maskColor: chatThemeData.colorTheme.barsBg,
tailCirclesSpacing: 1,
),
),
),
],
),
const SizedBox(height: 8),
Text(
reaction.user!.name.split(' ')[0],
style: chatThemeData.textTheme.footnoteBold,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
],
),
);
}
}
@@ -1,5 +1,14 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
/// {@template reactionIconBuilder}
/// Signature for a function that builds a reaction icon.
/// {@endtemplate}
typedef ReactionIconBuilder = Widget Function(
BuildContext context,
bool isHighlighted,
double iconSize,
);
/// {@template streamReactionIcon} /// {@template streamReactionIcon}
/// Reaction icon data /// Reaction icon data
/// {@endtemplate} /// {@endtemplate}
@@ -13,10 +22,6 @@ class StreamReactionIcon {
/// Type of reaction /// Type of reaction
final String type; final String type;
/// Asset to display for reaction /// {@macro reactionIconBuilder}
final Widget Function( final ReactionIconBuilder builder;
BuildContext,
bool highlighted,
double size,
) builder;
} }
@@ -165,7 +165,7 @@ class StreamChatConfigurationData {
return StreamSvgIcon.loveReaction( return StreamSvgIcon.loveReaction(
color: highlighted color: highlighted
? theme.colorTheme.accentPrimary ? theme.colorTheme.accentPrimary
: theme.primaryIconTheme.color!.withOpacity(0.5), : theme.primaryIconTheme.color,
size: size, size: size,
); );
}, },
@@ -177,7 +177,7 @@ class StreamChatConfigurationData {
return StreamSvgIcon.thumbsUpReaction( return StreamSvgIcon.thumbsUpReaction(
color: highlighted color: highlighted
? theme.colorTheme.accentPrimary ? theme.colorTheme.accentPrimary
: theme.primaryIconTheme.color!.withOpacity(0.5), : theme.primaryIconTheme.color,
size: size, size: size,
); );
}, },
@@ -189,7 +189,7 @@ class StreamChatConfigurationData {
return StreamSvgIcon.thumbsDownReaction( return StreamSvgIcon.thumbsDownReaction(
color: highlighted color: highlighted
? theme.colorTheme.accentPrimary ? theme.colorTheme.accentPrimary
: theme.primaryIconTheme.color!.withOpacity(0.5), : theme.primaryIconTheme.color,
size: size, size: size,
); );
}, },
@@ -201,7 +201,7 @@ class StreamChatConfigurationData {
return StreamSvgIcon.lolReaction( return StreamSvgIcon.lolReaction(
color: highlighted color: highlighted
? theme.colorTheme.accentPrimary ? theme.colorTheme.accentPrimary
: theme.primaryIconTheme.color!.withOpacity(0.5), : theme.primaryIconTheme.color,
size: size, size: size,
); );
}, },
@@ -213,7 +213,7 @@ class StreamChatConfigurationData {
return StreamSvgIcon.wutReaction( return StreamSvgIcon.wutReaction(
color: highlighted color: highlighted
? theme.colorTheme.accentPrimary ? theme.colorTheme.accentPrimary
: theme.primaryIconTheme.color!.withOpacity(0.5), : theme.primaryIconTheme.color,
size: size, size: size,
); );
}, },
@@ -126,8 +126,7 @@ class StreamChatThemeData {
StreamTextTheme textTheme, StreamTextTheme textTheme,
) { ) {
final accentColor = colorTheme.accentPrimary; final accentColor = colorTheme.accentPrimary;
final iconTheme = final iconTheme = IconThemeData(color: colorTheme.textLowEmphasis);
IconThemeData(color: colorTheme.textHighEmphasis.withOpacity(0.5));
final channelHeaderTheme = StreamChannelHeaderThemeData( final channelHeaderTheme = StreamChannelHeaderThemeData(
avatarTheme: StreamAvatarThemeData( avatarTheme: StreamAvatarThemeData(
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
@@ -184,11 +183,11 @@ class StreamChatThemeData {
createdAtStyle: createdAtStyle:
textTheme.footnote.copyWith(color: colorTheme.textLowEmphasis), textTheme.footnote.copyWith(color: colorTheme.textLowEmphasis),
repliesStyle: textTheme.footnoteBold.copyWith(color: accentColor), repliesStyle: textTheme.footnoteBold.copyWith(color: accentColor),
messageBackgroundColor: colorTheme.disabled, messageBackgroundColor: colorTheme.borders,
messageBorderColor: colorTheme.borders,
reactionsBackgroundColor: colorTheme.barsBg, reactionsBackgroundColor: colorTheme.barsBg,
reactionsBorderColor: colorTheme.borders, reactionsBorderColor: colorTheme.borders,
reactionsMaskColor: colorTheme.appBg, reactionsMaskColor: colorTheme.appBg,
messageBorderColor: colorTheme.disabled,
avatarTheme: StreamAvatarThemeData( avatarTheme: StreamAvatarThemeData(
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
constraints: const BoxConstraints.tightFor( constraints: const BoxConstraints.tightFor(
@@ -207,8 +206,8 @@ class StreamChatThemeData {
textTheme.body.copyWith(fontWeight: FontWeight.w400), textTheme.body.copyWith(fontWeight: FontWeight.w400),
), ),
otherMessageTheme: StreamMessageThemeData( otherMessageTheme: StreamMessageThemeData(
reactionsBackgroundColor: colorTheme.disabled, reactionsBackgroundColor: colorTheme.borders,
reactionsBorderColor: colorTheme.barsBg, reactionsBorderColor: colorTheme.borders,
reactionsMaskColor: colorTheme.appBg, reactionsMaskColor: colorTheme.appBg,
messageTextStyle: textTheme.body, messageTextStyle: textTheme.body,
createdAtStyle: createdAtStyle:
@@ -4,7 +4,7 @@ import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
bool get isWeb => CurrentPlatform.isWeb; bool get isWeb => CurrentPlatform.isWeb;
/// Returns true if the app is running in a mobile device. /// Returns true if the app is running in a mobile device.
bool get isMobileDevice => CurrentPlatform.isIos || CurrentPlatform.isAndroid; bool get isMobileDevice => true;
/// Returns true if the app is running in a desktop device. /// Returns true if the app is running in a desktop device.
bool get isDesktopDevice => bool get isDesktopDevice =>
@@ -22,7 +22,7 @@ bool get isDesktopVideoPlayerSupported =>
bool get isMobileDeviceOrWeb => isWeb || isMobileDevice; bool get isMobileDeviceOrWeb => isWeb || isMobileDevice;
/// Returns true if the app is running in a desktop or web. /// Returns true if the app is running in a desktop or web.
bool get isDesktopDeviceOrWeb => isWeb || isDesktopDevice; bool get isDesktopDeviceOrWeb => false;
/// Returns true if the app is running in a flutter test environment. /// Returns true if the app is running in a flutter test environment.
bool get isTestEnvironment => CurrentPlatform.isFlutterTest; bool get isTestEnvironment => CurrentPlatform.isFlutterTest;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB