add reaction picker
This commit is contained in:
@@ -1,209 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_flutter/src/reaction_picker.dart';
|
||||
import 'package:stream_chat_flutter/src/stream_channel.dart';
|
||||
|
||||
import '../stream_chat_flutter.dart';
|
||||
import 'message_input.dart';
|
||||
import 'stream_chat.dart';
|
||||
|
||||
class MessageActionsBottomSheet extends StatelessWidget {
|
||||
final Widget Function(BuildContext, Message) editMessageInputBuilder;
|
||||
final void Function(Message) onThreadTap;
|
||||
final Message message;
|
||||
final bool showReactions;
|
||||
final bool showDeleteMessage;
|
||||
final bool showEditMessage;
|
||||
final bool showReply;
|
||||
final Map<String, String> reactionToEmoji = const {
|
||||
'love': '❤️️',
|
||||
'haha': '😂',
|
||||
'like': '👍',
|
||||
'sad': '😕',
|
||||
'angry': '😡',
|
||||
'wow': '😲',
|
||||
};
|
||||
|
||||
const MessageActionsBottomSheet({
|
||||
Key key,
|
||||
this.message,
|
||||
this.showReactions,
|
||||
this.showDeleteMessage,
|
||||
this.showEditMessage,
|
||||
this.onThreadTap,
|
||||
this.showReply,
|
||||
this.editMessageInputBuilder,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final channel = StreamChannel.of(context).channel;
|
||||
return SafeArea(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
if (showReactions &&
|
||||
(message.status == MessageSendingStatus.SENT ||
|
||||
message.status == null))
|
||||
ReactionPicker(
|
||||
channel: channel,
|
||||
reactionToEmoji: reactionToEmoji,
|
||||
message: message,
|
||||
),
|
||||
if (showDeleteMessage) _buildDeleteButton(context),
|
||||
if (showEditMessage) _buildEditMessage(context),
|
||||
if (showReply &&
|
||||
(message.status == MessageSendingStatus.SENT ||
|
||||
message.status == null) &&
|
||||
message.parentId == null)
|
||||
_buildReplyButton(context),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
FlatButton _buildDeleteButton(BuildContext context) {
|
||||
return FlatButton(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
'Delete message',
|
||||
style:
|
||||
Theme.of(context).textTheme.headline5.copyWith(color: Colors.red),
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
StreamChat.of(context).client.deleteMessage(
|
||||
message,
|
||||
StreamChannel.of(context).channel.cid,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
FlatButton _buildEditMessage(BuildContext context) {
|
||||
return FlatButton(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
'Edit message',
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
),
|
||||
),
|
||||
onPressed: () async {
|
||||
Navigator.pop(context);
|
||||
_showEditBottomSheet(context);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _showEditBottomSheet(BuildContext context) {
|
||||
final channel = StreamChannel.of(context).channel;
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
elevation: 2,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
isScrollControlled: true,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(32),
|
||||
topRight: Radius.circular(32),
|
||||
),
|
||||
),
|
||||
builder: (context) {
|
||||
return StreamChannel(
|
||||
channel: channel,
|
||||
child: Flex(
|
||||
direction: Axis.vertical,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 16.0,
|
||||
left: 16.0,
|
||||
right: 16.0,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'Edit message',
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
),
|
||||
Container(
|
||||
height: 30,
|
||||
padding: const EdgeInsets.all(2.0),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: RawMaterialButton(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
elevation: 0,
|
||||
highlightElevation: 0,
|
||||
focusElevation: 0,
|
||||
disabledElevation: 0,
|
||||
hoverElevation: 0,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
fillColor:
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? Colors.white.withOpacity(.1)
|
||||
: Colors.black.withOpacity(.1),
|
||||
padding: EdgeInsets.all(4),
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
size: 15,
|
||||
color: StreamChatTheme.of(context)
|
||||
.primaryIconTheme
|
||||
.color,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.of(context).viewInsets.bottom,
|
||||
),
|
||||
child: editMessageInputBuilder != null
|
||||
? editMessageInputBuilder(context, message)
|
||||
: MessageInput(
|
||||
editMessage: message,
|
||||
onMessageSent: (_) {
|
||||
FocusScope.of(context).unfocus();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
FlatButton _buildReplyButton(BuildContext context) {
|
||||
return FlatButton(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
'Start a thread',
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
if (onThreadTap != null) {
|
||||
onThreadTap(message);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,10 @@ import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_flutter/src/reaction_picker.dart';
|
||||
import 'package:stream_chat_flutter/src/stream_channel.dart';
|
||||
|
||||
import '../stream_chat_flutter.dart';
|
||||
import 'message_input.dart';
|
||||
import 'message_widget.dart';
|
||||
import 'stream_chat.dart';
|
||||
import 'stream_chat_theme.dart';
|
||||
|
||||
class MessageActionsModal extends StatelessWidget {
|
||||
final Widget Function(BuildContext, Message) editMessageInputBuilder;
|
||||
@@ -21,14 +22,6 @@ class MessageActionsModal extends StatelessWidget {
|
||||
final bool showReply;
|
||||
final bool reverse;
|
||||
final ShapeBorder messageShape;
|
||||
final Map<String, String> reactionToEmoji = const {
|
||||
'love': '❤️️',
|
||||
'haha': '😂',
|
||||
'like': '👍',
|
||||
'sad': '😕',
|
||||
'angry': '😡',
|
||||
'wow': '😲',
|
||||
};
|
||||
|
||||
const MessageActionsModal({
|
||||
Key key,
|
||||
@@ -73,10 +66,12 @@ class MessageActionsModal extends StatelessWidget {
|
||||
if (showReactions &&
|
||||
(message.status == MessageSendingStatus.SENT ||
|
||||
message.status == null))
|
||||
ReactionPicker(
|
||||
channel: channel,
|
||||
reactionToEmoji: reactionToEmoji,
|
||||
message: message,
|
||||
Center(
|
||||
child: ReactionPicker(
|
||||
channel: channel,
|
||||
message: message,
|
||||
messageTheme: messageTheme,
|
||||
),
|
||||
),
|
||||
AbsorbPointer(
|
||||
child: MessageWidget(
|
||||
@@ -158,7 +153,7 @@ class MessageActionsModal extends StatelessWidget {
|
||||
alignment: Alignment.center,
|
||||
package: 'stream_chat_flutter',
|
||||
color: StreamChatTheme.of(context).primaryIconTheme.color,
|
||||
width: 17,
|
||||
width: 24,
|
||||
),
|
||||
onTap: () async {
|
||||
Navigator.pop(context);
|
||||
|
||||
+123
-35
@@ -5,6 +5,7 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_portal/flutter_portal.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:jiffy/jiffy.dart';
|
||||
import 'package:stream_chat_flutter/src/message_actions_modal.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
@@ -193,15 +194,6 @@ class MessageWidget extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MessageWidgetState extends State<MessageWidget> {
|
||||
final Map<String, String> _reactionToEmoji = {
|
||||
'love': '❤️️',
|
||||
'haha': '😂',
|
||||
'like': '👍',
|
||||
'sad': '😕',
|
||||
'angry': '😡',
|
||||
'wow': '😲',
|
||||
};
|
||||
|
||||
final GlobalKey _reactionPickerKey = GlobalKey();
|
||||
double _reactionPadding = 0;
|
||||
|
||||
@@ -341,9 +333,9 @@ class _MessageWidgetState extends State<MessageWidget> {
|
||||
offset: Offset(4, 0),
|
||||
child: CustomPaint(
|
||||
painter: ReactionBubblePainter(
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? Colors.white
|
||||
: Colors.black,
|
||||
widget.messageTheme.reactionsBackgroundColor,
|
||||
widget.messageTheme.reactionsBorderColor,
|
||||
widget.message.reactionCounts.length,
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -456,14 +448,23 @@ class _MessageWidgetState extends State<MessageWidget> {
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).brightness ==
|
||||
Brightness.dark
|
||||
? Colors.white
|
||||
: Colors.black,
|
||||
border: widget.messageTheme
|
||||
.reactionsBackgroundColor ==
|
||||
StreamChatTheme.of(context)
|
||||
.backgroundColor
|
||||
? Border.all(
|
||||
color: Theme.of(context).brightness ==
|
||||
Brightness.dark
|
||||
? Colors.white.withAlpha(24)
|
||||
: Colors.black.withAlpha(24),
|
||||
)
|
||||
: null,
|
||||
color:
|
||||
widget.messageTheme.reactionsBackgroundColor,
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(14)),
|
||||
),
|
||||
child: _buildReactionsText(context),
|
||||
child: _buildReactions(context),
|
||||
),
|
||||
),
|
||||
_buildReactionsTail(context),
|
||||
@@ -477,18 +478,33 @@ class _MessageWidgetState extends State<MessageWidget> {
|
||||
);
|
||||
}
|
||||
|
||||
Text _buildReactionsText(BuildContext context) {
|
||||
return Text(
|
||||
widget.message.reactionCounts.keys.map((reactionType) {
|
||||
return _reactionToEmoji[reactionType] ?? '?';
|
||||
}).join(' ') +
|
||||
' ${widget.message.reactionCounts.values.fold(0, (t, v) => v + t).toString()}',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).brightness == Brightness.dark
|
||||
? Colors.black
|
||||
: Colors.white,
|
||||
),
|
||||
textAlign: TextAlign.justify,
|
||||
Widget _buildReactions(BuildContext context) {
|
||||
final reactionAssets = StreamChatTheme.of(context).reactionAssets;
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
...widget.message.reactionCounts.keys.map((reactionType) {
|
||||
final reactionAsset = reactionAssets.firstWhere(
|
||||
(reactionAsset) => reactionAsset.type == reactionType,
|
||||
orElse: () => null,
|
||||
);
|
||||
if (reactionAsset == null) {
|
||||
return Text(
|
||||
'?',
|
||||
style: TextStyle(
|
||||
color: StreamChatTheme.of(context).accentColor,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return SvgPicture.asset(
|
||||
reactionAsset.svgAsset,
|
||||
package: reactionAsset.package,
|
||||
height: 16,
|
||||
color: StreamChatTheme.of(context).accentColor,
|
||||
);
|
||||
}).toList(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -807,17 +823,89 @@ class _MessageWidgetState extends State<MessageWidget> {
|
||||
|
||||
class ReactionBubblePainter extends CustomPainter {
|
||||
final Color color;
|
||||
final Color borderColor;
|
||||
final int reactionsCount;
|
||||
|
||||
ReactionBubblePainter(this.color);
|
||||
ReactionBubblePainter(
|
||||
this.color,
|
||||
this.borderColor,
|
||||
this.reactionsCount,
|
||||
);
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final paint = Paint()..color = color;
|
||||
_drawArc(size, canvas);
|
||||
|
||||
_drawBorder(size, canvas);
|
||||
|
||||
_drawOval(size, canvas);
|
||||
|
||||
_drawOvalBorder(size, canvas);
|
||||
}
|
||||
|
||||
void _drawOvalBorder(Size size, Canvas canvas) {
|
||||
final paint = Paint()
|
||||
..color = borderColor
|
||||
..strokeWidth = 1
|
||||
..style = PaintingStyle.stroke;
|
||||
|
||||
final path = Path();
|
||||
path.lineTo(-2, -6);
|
||||
path.lineTo(0, 10);
|
||||
path.lineTo(10, -6);
|
||||
path.lineTo(-2, -6);
|
||||
path.addOval(
|
||||
Rect.fromCircle(
|
||||
center: Offset(0, 3),
|
||||
radius: 2,
|
||||
),
|
||||
);
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
void _drawOval(Size size, Canvas canvas) {
|
||||
final paint = Paint()
|
||||
..color = color
|
||||
..strokeWidth = 1;
|
||||
|
||||
final path = Path();
|
||||
path.addOval(Rect.fromCircle(
|
||||
center: Offset(0, 3),
|
||||
radius: 2,
|
||||
));
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
void _drawBorder(Size size, Canvas canvas) {
|
||||
final paint = Paint()
|
||||
..color = borderColor
|
||||
..strokeWidth = 1
|
||||
..style = PaintingStyle.stroke;
|
||||
|
||||
final dy = reactionsCount > 1 ? -2.0 : -3.0;
|
||||
final path = Path();
|
||||
path.addArc(
|
||||
Rect.fromCircle(
|
||||
center: Offset(-4, dy),
|
||||
radius: 4,
|
||||
),
|
||||
-pi * 1.15,
|
||||
-pi / 1.4,
|
||||
);
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
void _drawArc(Size size, Canvas canvas) {
|
||||
final paint = Paint()
|
||||
..color = color
|
||||
..strokeWidth = 1;
|
||||
|
||||
final dy = reactionsCount > 1 ? -2.0 : -3.0;
|
||||
final path = Path();
|
||||
path.addArc(
|
||||
Rect.fromCircle(
|
||||
center: Offset(-4, dy),
|
||||
radius: 4,
|
||||
),
|
||||
-pi,
|
||||
-pi,
|
||||
);
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
class ReactionAsset {
|
||||
final String type;
|
||||
final String svgAsset;
|
||||
final String package;
|
||||
|
||||
ReactionAsset({
|
||||
this.type,
|
||||
this.svgAsset,
|
||||
this.package,
|
||||
});
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
import '../stream_chat_flutter.dart';
|
||||
|
||||
@@ -11,60 +12,54 @@ import '../stream_chat_flutter.dart';
|
||||
class ReactionPicker extends StatelessWidget {
|
||||
const ReactionPicker({
|
||||
Key key,
|
||||
@required this.reactionToEmoji,
|
||||
@required this.message,
|
||||
@required this.channel,
|
||||
this.size = 30,
|
||||
@required this.messageTheme,
|
||||
}) : super(key: key);
|
||||
|
||||
final Map<String, String> reactionToEmoji;
|
||||
final Message message;
|
||||
final double size;
|
||||
final MessageTheme messageTheme;
|
||||
final Channel channel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final reactionAssets = StreamChatTheme.of(context).reactionAssets;
|
||||
return Material(
|
||||
color: Colors.black87,
|
||||
color: messageTheme.reactionsBackgroundColor,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: reactionToEmoji.keys.map((reactionType) {
|
||||
final ownReactionIndex = message.ownReactions
|
||||
?.indexWhere((reaction) => reaction.type == reactionType) ??
|
||||
children: reactionAssets.map((reactionAsset) {
|
||||
final ownReactionIndex = message.ownReactions?.indexWhere(
|
||||
(reaction) => reaction.type == reactionAsset.type) ??
|
||||
-1;
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
IconButton(
|
||||
iconSize: size,
|
||||
icon: Text(
|
||||
reactionToEmoji[reactionType],
|
||||
style: TextStyle(
|
||||
fontSize: size - 10,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
if (ownReactionIndex != -1) {
|
||||
removeReaction(
|
||||
context, message.ownReactions[ownReactionIndex]);
|
||||
} else {
|
||||
sendReaction(context, reactionType);
|
||||
}
|
||||
},
|
||||
),
|
||||
ownReactionIndex != -1
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
message.ownReactions[ownReactionIndex].score.toString(),
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
)
|
||||
: SizedBox(),
|
||||
],
|
||||
return IconButton(
|
||||
iconSize: 24,
|
||||
icon: SvgPicture.asset(
|
||||
reactionAsset.svgAsset,
|
||||
package: reactionAsset.package,
|
||||
color: ownReactionIndex != -1
|
||||
? StreamChatTheme.of(context).accentColor
|
||||
: Colors.black,
|
||||
),
|
||||
onPressed: () {
|
||||
if (ownReactionIndex != -1) {
|
||||
removeReaction(
|
||||
context,
|
||||
message.ownReactions[ownReactionIndex],
|
||||
);
|
||||
} else {
|
||||
sendReaction(
|
||||
context,
|
||||
reactionAsset.type,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
|
||||
@@ -4,6 +4,8 @@ import 'package:stream_chat_flutter/src/channel_header.dart';
|
||||
import 'package:stream_chat_flutter/src/channel_preview.dart';
|
||||
import 'package:stream_chat_flutter/src/message_input.dart';
|
||||
|
||||
import 'reaction_asset.dart';
|
||||
|
||||
/// Inherited widget providing the [StreamChatThemeData] to the widget tree
|
||||
class StreamChatTheme extends InheritedWidget {
|
||||
final StreamChatThemeData data;
|
||||
@@ -72,6 +74,9 @@ class StreamChatThemeData {
|
||||
/// Primary icon theme
|
||||
final IconThemeData primaryIconTheme;
|
||||
|
||||
/// Assets used for rendering reactions
|
||||
final List<ReactionAsset> reactionAssets;
|
||||
|
||||
/// Create a theme from scratch
|
||||
StreamChatThemeData({
|
||||
this.primaryColor,
|
||||
@@ -85,6 +90,7 @@ class StreamChatThemeData {
|
||||
this.defaultChannelImage,
|
||||
this.defaultUserImage,
|
||||
this.primaryIconTheme,
|
||||
this.reactionAssets,
|
||||
});
|
||||
|
||||
/// Create a theme from a Material [Theme]
|
||||
@@ -135,6 +141,7 @@ class StreamChatThemeData {
|
||||
Widget Function(BuildContext, Channel) defaultChannelImage,
|
||||
Widget Function(BuildContext, User) defaultUserImage,
|
||||
IconThemeData primaryIconTheme,
|
||||
List<ReactionAsset> reactionAssets,
|
||||
}) =>
|
||||
StreamChatThemeData(
|
||||
primaryColor: primaryColor ?? this.primaryColor,
|
||||
@@ -203,6 +210,7 @@ class StreamChatThemeData {
|
||||
this.otherMessageTheme.avatarTheme,
|
||||
) ??
|
||||
this.otherMessageTheme,
|
||||
reactionAssets: reactionAssets ?? this.reactionAssets,
|
||||
);
|
||||
|
||||
/// Get the default Stream Chat theme
|
||||
@@ -293,7 +301,9 @@ class StreamChatThemeData {
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
messageBackgroundColor: isDark ? Color(0xff191919) : Color(0xffE6E6E6),
|
||||
messageBackgroundColor: isDark ? Color(0xff191919) : Color(0xffEAEAEA),
|
||||
reactionsBackgroundColor: isDark ? Colors.black : Colors.white,
|
||||
reactionsBorderColor: isDark ? Color(0xff191919) : Color(0xffEAEAEA),
|
||||
avatarTheme: AvatarTheme(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
constraints: BoxConstraints.tightFor(
|
||||
@@ -306,6 +316,9 @@ class StreamChatThemeData {
|
||||
),
|
||||
),
|
||||
otherMessageTheme: MessageTheme(
|
||||
reactionsBackgroundColor:
|
||||
isDark ? Color(0xff191919) : Color(0xffEAEAEA),
|
||||
reactionsBorderColor: theme.scaffoldBackgroundColor,
|
||||
messageText: TextStyle(
|
||||
fontSize: 15,
|
||||
color: isDark ? Colors.white : Colors.black,
|
||||
@@ -333,6 +346,33 @@ class StreamChatThemeData {
|
||||
),
|
||||
),
|
||||
),
|
||||
reactionAssets: [
|
||||
ReactionAsset(
|
||||
type: 'love',
|
||||
svgAsset: 'assets/Icon_love_reaction.svg',
|
||||
package: 'stream_chat_flutter',
|
||||
),
|
||||
ReactionAsset(
|
||||
type: 'thumbs_up',
|
||||
svgAsset: 'assets/Icon_thumbs_up_reaction.svg',
|
||||
package: 'stream_chat_flutter',
|
||||
),
|
||||
ReactionAsset(
|
||||
type: 'thumbs_down',
|
||||
svgAsset: 'assets/Icon_thumbs_down_reaction.svg',
|
||||
package: 'stream_chat_flutter',
|
||||
),
|
||||
ReactionAsset(
|
||||
type: 'lol',
|
||||
svgAsset: 'assets/Icon_LOL_reaction.svg',
|
||||
package: 'stream_chat_flutter',
|
||||
),
|
||||
ReactionAsset(
|
||||
type: 'wut',
|
||||
svgAsset: 'assets/Icon_wut_reaction.svg',
|
||||
package: 'stream_chat_flutter',
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -415,6 +455,8 @@ class MessageTheme {
|
||||
final TextStyle createdAt;
|
||||
final TextStyle replies;
|
||||
final Color messageBackgroundColor;
|
||||
final Color reactionsBackgroundColor;
|
||||
final Color reactionsBorderColor;
|
||||
final AvatarTheme avatarTheme;
|
||||
|
||||
const MessageTheme({
|
||||
@@ -423,6 +465,8 @@ class MessageTheme {
|
||||
this.messageAuthor,
|
||||
this.messageLinks,
|
||||
this.messageBackgroundColor,
|
||||
this.reactionsBackgroundColor,
|
||||
this.reactionsBorderColor,
|
||||
this.avatarTheme,
|
||||
this.createdAt,
|
||||
});
|
||||
@@ -436,6 +480,8 @@ class MessageTheme {
|
||||
Color messageBackgroundColor,
|
||||
Color otherMessageBackgroundColor,
|
||||
AvatarTheme avatarTheme,
|
||||
Color reactionsBackgroundColor,
|
||||
Color reactionsBorderColor,
|
||||
}) =>
|
||||
MessageTheme(
|
||||
messageText: messageText ?? this.messageText,
|
||||
@@ -446,6 +492,9 @@ class MessageTheme {
|
||||
messageBackgroundColor ?? this.messageBackgroundColor,
|
||||
avatarTheme: avatarTheme ?? this.avatarTheme,
|
||||
replies: replies ?? this.replies,
|
||||
reactionsBackgroundColor:
|
||||
reactionsBackgroundColor ?? this.reactionsBackgroundColor,
|
||||
reactionsBorderColor: reactionsBorderColor ?? this.reactionsBorderColor,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user