Merge pull request #474 from GetStream/feat/customReaction
feat: let users use custom reaction builders
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
- Performance improvements
|
||||
- Added pinMessage ui support
|
||||
- Added `MessageListView.threadSeparatorBuilder` property
|
||||
|
||||
## 2.0.0-nullsafety.4
|
||||
|
||||
- Minor fixes and improvements
|
||||
|
||||
@@ -148,6 +148,10 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
||||
|
||||
final streamChatThemeData = StreamChatTheme.of(context);
|
||||
|
||||
final numberOfReactions = streamChatThemeData.reactionIcons.length;
|
||||
final shiftFactor =
|
||||
numberOfReactions < 5 ? (5 - numberOfReactions) * 0.1 : 0.0;
|
||||
|
||||
final child = Center(
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
@@ -162,8 +166,12 @@ class _MessageActionsModalState extends State<MessageActionsModal> {
|
||||
Align(
|
||||
alignment: Alignment(
|
||||
user?.id == widget.message.user?.id
|
||||
? (divFactor >= 1.0 ? -0.2 : (1.2 - divFactor))
|
||||
: (divFactor >= 1.0 ? 0.2 : -(1.2 - divFactor)),
|
||||
? (divFactor >= 1.0
|
||||
? -0.2 - shiftFactor
|
||||
: (1.2 - divFactor))
|
||||
: (divFactor >= 1.0
|
||||
? 0.2 + shiftFactor
|
||||
: -(1.2 - divFactor)),
|
||||
0),
|
||||
child: ReactionPicker(
|
||||
message: widget.message,
|
||||
|
||||
@@ -80,6 +80,10 @@ class MessageReactionsModal extends StatelessWidget {
|
||||
final hasFileAttachment =
|
||||
message.attachments.any((it) => it.type == 'file') == true;
|
||||
|
||||
final numberOfReactions = StreamChatTheme.of(context).reactionIcons.length;
|
||||
final shiftFactor =
|
||||
numberOfReactions < 5 ? (5 - numberOfReactions) * 0.1 : 0.0;
|
||||
|
||||
final child = Center(
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
@@ -93,8 +97,12 @@ class MessageReactionsModal extends StatelessWidget {
|
||||
Align(
|
||||
alignment: Alignment(
|
||||
user!.id == message.user!.id
|
||||
? (divFactor >= 1.0 ? -0.2 : (1.2 - divFactor))
|
||||
: (divFactor >= 1.0 ? 0.2 : -(1.2 - divFactor)),
|
||||
? (divFactor >= 1.0
|
||||
? -0.2 - shiftFactor
|
||||
: (1.2 - divFactor))
|
||||
: (divFactor >= 1.0
|
||||
? 0.2 + shiftFactor
|
||||
: -(1.2 - divFactor)),
|
||||
0),
|
||||
child: ReactionPicker(
|
||||
message: message,
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:stream_chat_flutter/src/reaction_icon.dart';
|
||||
import 'package:stream_chat_flutter/src/stream_svg_icon.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
|
||||
/// Creates reaction bubble widget for displaying over messages
|
||||
@@ -130,13 +129,13 @@ class ReactionBubble extends StatelessWidget {
|
||||
horizontal: 4,
|
||||
),
|
||||
child: reactionIcon != null
|
||||
? StreamSvgIcon(
|
||||
assetName: reactionIcon.assetName,
|
||||
width: 16,
|
||||
height: 16,
|
||||
color: (!highlightOwnReactions || reaction.user?.id == userId)
|
||||
? chatThemeData.colorTheme.accentBlue
|
||||
: chatThemeData.colorTheme.black.withOpacity(.5),
|
||||
? ConstrainedBox(
|
||||
constraints: BoxConstraints.tight(const Size.square(16)),
|
||||
child: reactionIcon.builder(
|
||||
context,
|
||||
!highlightOwnReactions || reaction.user?.id == userId,
|
||||
16,
|
||||
),
|
||||
)
|
||||
: Icon(
|
||||
Icons.help_outline_rounded,
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Reaction icon data
|
||||
class ReactionIcon {
|
||||
/// Constructor for creating [ReactionIcon]
|
||||
ReactionIcon({
|
||||
required this.type,
|
||||
required this.assetName,
|
||||
required this.builder,
|
||||
});
|
||||
|
||||
/// Type of reaction
|
||||
final String type;
|
||||
|
||||
/// Asset to display for reaction
|
||||
final String assetName;
|
||||
final Widget Function(
|
||||
BuildContext,
|
||||
bool highlighted,
|
||||
double size,
|
||||
) builder;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:ezanimation/ezanimation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stream_chat_flutter/src/extension.dart';
|
||||
import 'package:stream_chat_flutter/src/stream_svg_icon.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
|
||||
/// 
|
||||
@@ -69,11 +68,10 @@ class _ReactionPickerState extends State<ReactionPicker>
|
||||
-1;
|
||||
final index = reactionIcons.indexOf(reactionIcon);
|
||||
|
||||
final child = StreamSvgIcon(
|
||||
assetName: reactionIcon.assetName,
|
||||
color: ownReactionIndex != -1
|
||||
? chatThemeData.colorTheme.accentBlue
|
||||
: Theme.of(context).iconTheme.color!.withOpacity(.5),
|
||||
final child = reactionIcon.builder(
|
||||
context,
|
||||
ownReactionIndex != -1,
|
||||
24,
|
||||
);
|
||||
|
||||
return ConstrainedBox(
|
||||
|
||||
@@ -217,10 +217,11 @@ class StreamChatThemeData {
|
||||
TextTheme textTheme,
|
||||
) {
|
||||
final accentColor = colorTheme.accentBlue;
|
||||
final iconTheme = IconThemeData(color: colorTheme.black.withOpacity(.5));
|
||||
return StreamChatThemeData.raw(
|
||||
textTheme: textTheme,
|
||||
colorTheme: colorTheme,
|
||||
primaryIconTheme: IconThemeData(color: colorTheme.black.withOpacity(.5)),
|
||||
primaryIconTheme: iconTheme,
|
||||
defaultChannelImage: (context, channel) => const SizedBox(),
|
||||
defaultUserImage: (context, user) => Center(
|
||||
child: CachedNetworkImage(
|
||||
@@ -342,23 +343,63 @@ class StreamChatThemeData {
|
||||
reactionIcons: [
|
||||
ReactionIcon(
|
||||
type: 'love',
|
||||
assetName: 'Icon_love_reaction.svg',
|
||||
builder: (context, highlighted, size) {
|
||||
final theme = StreamChatTheme.of(context);
|
||||
return StreamSvgIcon.loveReaction(
|
||||
color: highlighted
|
||||
? theme.colorTheme.accentBlue
|
||||
: theme.primaryIconTheme.color!.withOpacity(.5),
|
||||
size: size,
|
||||
);
|
||||
},
|
||||
),
|
||||
ReactionIcon(
|
||||
type: 'like',
|
||||
assetName: 'Icon_thumbs_up_reaction.svg',
|
||||
builder: (context, highlighted, size) {
|
||||
final theme = StreamChatTheme.of(context);
|
||||
return StreamSvgIcon.thumbsUpReaction(
|
||||
color: highlighted
|
||||
? theme.colorTheme.accentBlue
|
||||
: theme.primaryIconTheme.color!.withOpacity(.5),
|
||||
size: size,
|
||||
);
|
||||
},
|
||||
),
|
||||
ReactionIcon(
|
||||
type: 'sad',
|
||||
assetName: 'Icon_thumbs_down_reaction.svg',
|
||||
builder: (context, highlighted, size) {
|
||||
final theme = StreamChatTheme.of(context);
|
||||
return StreamSvgIcon.thumbsDownReaction(
|
||||
color: highlighted
|
||||
? theme.colorTheme.accentBlue
|
||||
: theme.primaryIconTheme.color!.withOpacity(.5),
|
||||
size: size,
|
||||
);
|
||||
},
|
||||
),
|
||||
ReactionIcon(
|
||||
type: 'haha',
|
||||
assetName: 'Icon_LOL_reaction.svg',
|
||||
builder: (context, highlighted, size) {
|
||||
final theme = StreamChatTheme.of(context);
|
||||
return StreamSvgIcon.lolReaction(
|
||||
color: highlighted
|
||||
? theme.colorTheme.accentBlue
|
||||
: theme.primaryIconTheme.color!.withOpacity(.5),
|
||||
size: size,
|
||||
);
|
||||
},
|
||||
),
|
||||
ReactionIcon(
|
||||
type: 'wow',
|
||||
assetName: 'Icon_wut_reaction.svg',
|
||||
builder: (context, highlighted, size) {
|
||||
final theme = StreamChatTheme.of(context);
|
||||
return StreamSvgIcon.wutReaction(
|
||||
color: highlighted
|
||||
? theme.colorTheme.accentBlue
|
||||
: theme.primaryIconTheme.color!.withOpacity(.5),
|
||||
size: size,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -49,6 +49,66 @@ class StreamSvgIcon extends StatelessWidget {
|
||||
height: size,
|
||||
);
|
||||
|
||||
/// [StreamSvgIcon] type
|
||||
factory StreamSvgIcon.loveReaction({
|
||||
double? size,
|
||||
Color? color,
|
||||
}) =>
|
||||
StreamSvgIcon(
|
||||
assetName: 'Icon_love_reaction.svg',
|
||||
color: color,
|
||||
width: size,
|
||||
height: size,
|
||||
);
|
||||
|
||||
/// [StreamSvgIcon] type
|
||||
factory StreamSvgIcon.thumbsUpReaction({
|
||||
double? size,
|
||||
Color? color,
|
||||
}) =>
|
||||
StreamSvgIcon(
|
||||
assetName: 'Icon_thumbs_up_reaction.svg',
|
||||
color: color,
|
||||
width: size,
|
||||
height: size,
|
||||
);
|
||||
|
||||
/// [StreamSvgIcon] type
|
||||
factory StreamSvgIcon.thumbsDownReaction({
|
||||
double? size,
|
||||
Color? color,
|
||||
}) =>
|
||||
StreamSvgIcon(
|
||||
assetName: 'Icon_thumbs_down_reaction.svg',
|
||||
color: color,
|
||||
width: size,
|
||||
height: size,
|
||||
);
|
||||
|
||||
/// [StreamSvgIcon] type
|
||||
factory StreamSvgIcon.lolReaction({
|
||||
double? size,
|
||||
Color? color,
|
||||
}) =>
|
||||
StreamSvgIcon(
|
||||
assetName: 'Icon_LOL_reaction.svg',
|
||||
color: color,
|
||||
width: size,
|
||||
height: size,
|
||||
);
|
||||
|
||||
/// [StreamSvgIcon] type
|
||||
factory StreamSvgIcon.wutReaction({
|
||||
double? size,
|
||||
Color? color,
|
||||
}) =>
|
||||
StreamSvgIcon(
|
||||
assetName: 'Icon_wut_reaction.svg',
|
||||
color: color,
|
||||
width: size,
|
||||
height: size,
|
||||
);
|
||||
|
||||
/// [StreamSvgIcon] type
|
||||
factory StreamSvgIcon.smile({
|
||||
double? size,
|
||||
|
||||
Reference in New Issue
Block a user